简体   繁体   中英

Find cycle in directed graph using BFS?

I thought about flagging all nodes that I visited. When I found some node that have flag set is it cycle. But this wont work because one node can have multiple parents and multiple child's. How can I do it to find cycle?

PS: I know that for finding cycle is more suitable DFS, but I need to do it by BFS.

To find out whether a direct graph contains a cycle or not is the same problem as determining whether or not the graph has a topological sorting/order. That is, finding out if all of the vertices of the graph can be arranged in a linear fashion where all of the outbound edges of any one vertex always point towards another vertex further to its right.

The concept is this; a graph that has a topological sorting, aka a directed acyclic graph (DAG), will always have at least one vertex that does not have any in-bound edges. You can easily prove this statement by contradiction: if every vertex had an in-bound edge, walking backwards through the graph would eventually result in visiting a vertex twice in one walk, meaning that it has a cycle, and it is not a DAG.

Removing vertices and its out-bound edges from a DAG will never cause a new cycle to be created. In the linear visual representation of a topological order, the leftmost vertex has no in-bound edges. If one were to remove the leftmost vertex and its edges in a topological order one by one, they would always be removing vertices that do not have in-bound edges since they either started without any, or its in-bound edges were removed by other vertices being removed. Only vertices that do not have any in-bound edges nor out-bound edges would remain, before being removed themselves.

If removing every vertex with no in-bound edges sequentially did not clear every vertex off of the graph, that means that a cycle exists in the graph and it is not a DAG.


Following that idea, an algorithm you could use with a FIFO data structure to support BFS would be to first determine the number of in-bound edges on all vertices. You can achieve this by performing a BFS at the beginning, and for every out-bound edge discovered, increment the in-bound edge counter of that corresponding neighbor in its main adjacency list node.

Onto the meat of the algorithm, you would want to search through the vertices and add the ones that currently have no in-bound edges to the queue. After adding all of the currently available ones, go from the front of the queue and examine the vertex. Remove it from the graph by walking through its neighbors and decrementing each respective in-bound edges count by 1, as well as checking whether the new count had reached zero or not. If it did, then add that vertex into the queue. After finishing the decrementing, move onto the next vertex in the queue. Continue the same process for all vertices on the queue. This process can look like multiple BFS originating from each vertex that had no in-bound edges.

At the end, if the number of removed vertices is the same as the total number of vertices, the graph was a DAG and contains no cycles. If not, that means there are vertices remaining that are part of a cycle/cycles.

Though this question is pretty old, I wish you best of luck!

The answer above is correct but I think it is not a BFS or at least not an intuitive BFS. It mainly depends on checking the outgoing edges of each node and deleting the edges connected to the nodes without incoming edges. My answer may be a more intuitive BFS implementation on this problem.

Let's think about what is cycle?

A node can find a path to reach himself, then there is a cycle.

Then why DFS can solve the finding cycle task while BFS can't?

To find the cycle in a directed graph, we first come up with DFS: If there is a back edge in the DFS tree, then there will be cycle in the graph. When building up the DFS tree, we can record the starting counter and end counter for each node so that we can check if the pointing node is the current node's ancestor. Once the back edge is found (pointing node is not finished but starts before current node), it means that the node can find a way back to one of its ancestors. While the BFS is used to fully explore one's neighbors but can't save the ancestors. So, maybe we can make BFS work on this problem if save the ancestors when go through the graph:

During the BFS, when each node explores its neighbors (or children),sends the accumulated ancestor information to their neighbors. When a node finds one of the ancestors passed from his parent is himself, then there is a cycle in the graph. Here is a picture shows the step of this algorithm: 在此处输入图片说明

Step 1, A explores his neighbors: B, C, D, E and send the ancestor information {A} to them.

Step 2, B explores his neighbors E and send the ancestor information {A, B} to it.

Step 3, C explores his neighbors D, F and send ancestor information {A, C} to them.

Step 4, D finds no neighbors.

Step 5, F explores his neighbors D, G and send ancestor information {A, C, F} to them.

Step 6, G explores his neighbors C and send ancestor information {A, C, F, G} to it. Then C will find that his ancestor is himself, then there will be a cycle.

Then, how about the running time of this algorithm? The running time of traditional BFS is Theta(V+E), but in this algorithm, passing and union of the ancestor information, will take total E steps, while in each step information array size is larger than 1 less than C*V. So the total running time is O(EV), Omega(V+E).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM