Given an undirected graph G=(V,E) with n vertices ( |V| = n ), how do you find if it contains a cycle in O(n) ?
I think that depth first search solves it. If an unexplored edge leads to a node visited before, then the graph contains a cycle. This condition also makes it O(n), since you can explore maximum n edges without setting it to true or being left with no unexplored edges.
The answer is, really, breadth first search (or depth first search, it doesn't really matter). The details lie in the analysis.
Now, how fast is the algorithm?
First, imagine the graph has no cycles. The number of edges is then O(V), the graph is a forest, goal reached.
Now, imagine the graph has cycles, and your searching algorithm will finish and report success in the first of them. The graph is undirected, and therefore, the when the algorithm inspects an edge, there are only two possibilities: Either it has visited the other end of the edge, or it has and then, this edge closes a circle. And once it sees the other vertex of the edge, that vertex is "inspected", so there are only O(V) of these operations. The second case will be reached only once throughout the run of the algorithm.
Actually, depth first (or indeed breadth first) search isn't quite enough. You need a sightly more complex algorithm.
For instance, suppose there is graph with nodes {a,b,c,d} and edges {(a,b),(b,c),(b,d),(d,c)} where an edge (x,y) is an edge from x to y. (looks something like this, with all edges directed downwards.)
(a)
|
|
(b)
/ \
(d) |
| |
\ /
(c)
Then doing depth first search may visit node a, then b then c then backtrack to c then visit d and finally visit c again and conclude there is a cycle when there isn't. A similar thing happens with breadth first.
What you need to do is keep track of which nodes your in the middle of visiting. In the example above, when the algorithm reaches (d) it has finished visiting (c) but not (a) or (b). So revisiting a finished node is fine, but visiting an unfinished node means you have a cycle. The usual way to do this is colour each node white(not yet visited), grey(visiting descendants) or black(finished visiting).
here is some pseudo code!
define visit(node n):
if n.colour == grey: //if we're still visiting this node or its descendants
throw exception("Cycle found")
n.colour = grey //to indicate this node is being visited
for node child in n.children():
if child.colour == white: //if the child is unexplored
visit(child)
n.colour = black //to show we're done visiting this node
return
then running visit(root_node) will throw an exception if and only if there is a cycle (initially all nodes should be white).
Sorry if you knew all this already, it may well be what you meant by depth first search anyway, but I hope it helps.
I have a similar problem, but I want to have all cycles in undirected graph. Is there any polynomial algorithm?
I believe that the assumption that the graph is connected can be handful. thus, you can use the proof shown above, that the running time is O(|V|). if not, then |E|>|V|. reminder: the running time of DFS is O(|V|+|E|).