views:

3069

answers:

4

How do I check if a directed graph is acyclic? And how is the algorithm called? I would appreciate a reference. Niko

+1  A: 

The solution given by ShuggyCoUk is incomplete because it might not check all nodes.


def isDAG(nodes V):
    while there is an unvisited node v in V:
        bool cycleFound = dfs(v)
        if cyclefound:
            return false
    return true

This has timecomplexity O(n+m) or O(n^2)

mine is indeed incorrect - I deleted it though so your's now seems a little out of context
ShuggyCoUk
+8  A: 

Doing a simple depth-first-search is not good enough to find a cycle. It is possible to visit a node multiple times in a DFS without a cycle existing. Depending on where you start, you also might not visit the entire graph.

You can check for cycles in a connected component of a graph as follows. Find a node which has only outgoing edges. If there is no such node, then there is a cycle. Start a DFS at that node. When traversing each edge, check whether the edge points back to a node already on your stack. This indicates the existence of a cycle. If you find no such edge, there are no cycles in that connected component.

As Rutger Prins points out, if your graph is not connected, you need to repeat the search on each connected component.

As a reference, Tarjan's strongly connected component algorithm is closely related. It will also help you find the cycles, not just report whether they exist.

Jay Conrod
BTW: An edge that "points back to a node already on your stack" is often called a "back edge" in the literature, for obvious reasons. And yes, this may be simpler than sorting the graph topologically, especially if you need to do a DFS anyway.
sleske
For the graph to be acyclic, you say that each connected component must contain a node with only outgoing edges. Can you recommend an algorithm to find the connected components (as opposed to "strongly" connected components) of a directed graph, for use by your main algorithm?
kostmo
@kostmo, if the graph has more than one connected component, then you will not visit all the nodes in your first DFS. Keep track of the nodes you've visited, and repeat the algorithm with unvisited nodes until you reach them all. This is basically how a connected components algorithm works anyway.
Jay Conrod
+11  A: 

I would try to sort the graph topologically, and if you can't, then it has cycles.

FryGuy
How did this have no votes?? It's linear on nodes + edges, far superior to the O(n^2) solutions!
Loren Pechtel
I just answered it :)
FryGuy
In many cases, a DFS (see J.Conrod's answer) may be easier, especially if a DFS needs to be performed anyway. But of course this depends on the context.
sleske
+2  A: 

Lemma 22.11 on the Book Introduction to Algorithms (Second Edition) states that:

"A directed graph G is acyclic if and only if a depth-first search of G yields no back edges"

Miguel Fonseca
This is basically just an abbreviated version of Jay Conrod's answer :-).
sleske