@@ -517,6 +517,16 @@ namespace CXXGRAPH
517
517
* @return true if a cycle is detected, else false. ( false is returned also if the graph in indirected)
518
518
*/
519
519
const bool isCyclicDirectedGraphDFS () const ;
520
+
521
+ /* *
522
+ * \brief
523
+ * This function uses BFS to check for cycle in the graph.
524
+ * Pay Attention, this function work only with directed Graph
525
+ *
526
+ * @return true if a cycle is detected, else false. ( false is returned also if the graph in indirected)
527
+ */
528
+ const bool isCyclicDirectedGraphBFS () const ;
529
+
520
530
/* *
521
531
* \brief
522
532
* This function checks if a graph is directed
@@ -807,7 +817,8 @@ namespace CXXGRAPH
807
817
template <typename T>
808
818
const bool Graph<T>::isCyclicDirectedGraphDFS() const
809
819
{
810
- if (!isDirectedGraph ()){
820
+ if (!isDirectedGraph ())
821
+ {
811
822
return false ;
812
823
}
813
824
enum nodeStates : uint8_t
@@ -826,8 +837,9 @@ namespace CXXGRAPH
826
837
*
827
838
* Initially, all nodes are in "not_visited" state.
828
839
*/
829
- std::map<unsigned long ,nodeStates> state;
830
- for (auto node : nodeSet){
840
+ std::map<unsigned long , nodeStates> state;
841
+ for (auto node : nodeSet)
842
+ {
831
843
state[node->getId ()] = not_visited;
832
844
}
833
845
int stateCounter = 0 ;
@@ -841,8 +853,8 @@ namespace CXXGRAPH
841
853
if (state[node->getId ()] == not_visited)
842
854
{
843
855
// Check for cycle.
844
- std::function<bool (AdjacencyMatrix<T>&, std::map<unsigned long ,nodeStates>&, const Node<T>*)> isCyclicDFSHelper;
845
- isCyclicDFSHelper = [this , &isCyclicDFSHelper](AdjacencyMatrix<T>& adjMatrix, std::map<unsigned long ,nodeStates>& states, const Node<T>* node)
856
+ std::function<bool (AdjacencyMatrix<T> &, std::map<unsigned long , nodeStates> &, const Node<T> *)> isCyclicDFSHelper;
857
+ isCyclicDFSHelper = [this , &isCyclicDFSHelper](AdjacencyMatrix<T> & adjMatrix, std::map<unsigned long , nodeStates> & states, const Node<T> * node)
846
858
{
847
859
// Add node "in_stack" state.
848
860
states[node->getId ()] = in_stack;
@@ -891,13 +903,84 @@ namespace CXXGRAPH
891
903
// the graph. Return false.
892
904
return false ;
893
905
}
894
-
895
- template <typename T>
906
+
907
+ template <typename T>
908
+ const bool Graph<T>::isCyclicDirectedGraphBFS() const
909
+ {
910
+ if (!isDirectedGraph ())
911
+ {
912
+ return false ;
913
+ }
914
+ auto adjMatrix = this ->getAdjMatrix ();
915
+ auto nodeSet = this ->getNodeSet ();
916
+
917
+ std::map<unsigned long , unsigned int > indegree;
918
+ for (auto node : nodeSet)
919
+ {
920
+ indegree[node->getId ()] = 0 ;
921
+ }
922
+ // Calculate the indegree i.e. the number of incident edges to the node.
923
+ for (auto const &list : adjMatrix)
924
+ {
925
+ auto children = list.second ;
926
+ for (auto const &child : children)
927
+ {
928
+ indegree[std::get<0 >(child)->getId ()]++;
929
+ }
930
+ }
931
+
932
+ std::queue<const Node<T> *> can_be_solved;
933
+ for (auto node : nodeSet)
934
+ {
935
+ // If a node doesn't have any input edges, then that node will
936
+ // definately not result in a cycle and can be visited safely.
937
+ if (!indegree[node->getId ()])
938
+ {
939
+ can_be_solved.emplace (&(*node));
940
+ }
941
+ }
942
+
943
+ // Vertices that need to be traversed.
944
+ auto remain = this ->getNodeSet ().size ();
945
+ // While there are safe nodes that we can visit.
946
+ while (!can_be_solved.empty ())
947
+ {
948
+ auto solved = can_be_solved.front ();
949
+ // Visit the node.
950
+ can_be_solved.pop ();
951
+ // Decrease number of nodes that need to be traversed.
952
+ remain--;
953
+
954
+ // Visit all the children of the visited node.
955
+ auto it = adjMatrix.find (solved);
956
+ if (it != adjMatrix.end ())
957
+ {
958
+ for (auto child : it->second )
959
+ {
960
+ // Check if we can visited the node safely.
961
+ if (--indegree[std::get<0 >(child)->getId ()] == 0 )
962
+ {
963
+ // if node can be visited safely, then add that node to
964
+ // the visit queue.
965
+ can_be_solved.emplace (std::get<0 >(child));
966
+ }
967
+ }
968
+ }
969
+ }
970
+
971
+ // If there are still nodes that we can't visit, then it means that
972
+ // there is a cycle and return true, else return false.
973
+ return !(remain == 0 );
974
+ }
975
+
976
+ template <typename T>
896
977
const bool Graph<T>::isDirectedGraph() const
897
978
{
898
979
auto edgeSet = this ->getEdgeSet ();
899
- for ( auto edge : edgeSet){
900
- if ( !(edge->isDirected ().has_value () && edge->isDirected ().value ())){
980
+ for (auto edge : edgeSet)
981
+ {
982
+ if (!(edge->isDirected ().has_value () && edge->isDirected ().value ()))
983
+ {
901
984
// Found Undirected Edge
902
985
return false ;
903
986
}
0 commit comments