Algorithm for searching and printing a simple cycle in complexity O (n) on an undirected graph
The specified graph G(V,E),
undirected graph.
|E| = m, |V| = n
Graph data structure is Adjacency list
How to find and print a simple cycle (or print that there is no such cycle) in complexity O(n)
?
(If there is a loop, the output must be a list of vertices that are part of the loop.)
I know how to find a cycle in difficulty O(n)
, there are homosexuals on the Internet as well.
My problem is how to print .
Here's what I tried to do:
DFS-CheckCycle ( Graph G)
{
p[] <- null //parent array
foreach v in V
Color[u] <- white
foreach v in V
{
if (Color[u] = white)
Visit(u)
}
}
Visit(Vertex u)
{
bool Cycle <- false;
Color[u] <- gray
foreach v in Adj[u]
{
p[v] <- u
if (Color[v] = white)
Visit(v);
else if (Color[v] = gray)
{
Cycle <- true;
break;
}
}
if(!Cycle)
print "No Cycle"
else
PrintCycle(v,u)
}
PrintCycle(Vertex v, Vertex u)
{
if(v = u)
print v;
else
{
print v;
PrintCycle(p[v], u);
}
}
remember what it should be O(n)
.
My PrintCycle function doesn't print all vertices.
I need help on how to print the vertices of the found loop.
source to share
I noticed two things that don't seem to be correct in your algorithm. First, when you use your DFS walk, you must maintain the following invariant:
- Unused vertices should be painted white; (You did it)
- Visited vertices, for which
Visit()
it is not finished yet, should be colored gray; - Visited vertices, for which it
Visit()
returned, should be colored black (or a color other than gray or white).
Another thing I noticed is that you have incorrectly assigned parents for the nodes. In your method, Visit()
parents are assigned even if the vertex we want to visit in the next step is gray, that is, it already has a parent in the DFS tree.
So I would change your code accordingly:
DFS-CheckCycle ( Graph G)
{
p[] <- null //parent array
foreach v in V
Color[v] <- white
foreach u in V
{
if (Color[u] = white) {
p[u] <- -1; // meaning it is a root of a DFS-tree of the DFS forest
Visit(u)
}
}
}
Visit(Vertex u)
{
bool Cycle <- false;
Color[u] <- gray
foreach v in Adj[u]
{
if (Color[v] = white) {
p[v] <- u
Visit(v);
}
else if (Color[v] = gray)
{
Cycle <- true;
break;
}
}
Color[u] <- black; // once DFS for this vertex ends, assign its color to black
if(!Cycle)
print "No Cycle"
else
PrintCycle(v,u)
}
PrintCycle(Vertex v, Vertex u)
{
if(v = u)
print v;
else
{
print v;
PrintCycle(p[v], u);
}
}
EDIT: It might be a good idea to turn your method PrintCycle
into a non-recursive one:
PrintCycle(Vertex v, Vertex u)
{
do {
print u;
u = p[u];
} while (u != v);
}
source to share
In recursive search, you can add a parameter that is a chain of ancestors up to the root of the search. The loop will consist of the current node, and in a chain ending at the gray node found to detect the loop.
By chain, I mean a list of lisp-styles: a pair consisting of a node and another pair, with the last pair being null.
An easier way is to search with an explicit stack rather than recursion. The nodes on the stack are gray. When you find a gray dial node, the loop can be printed out by traversing back through the stack.
source to share