给定graph G(V,E),
无方向图。
|E| = m, |V| = n
图表的数据结构是邻接列表
如何在O(n)
的复杂程度中找到并打印简单周期(或打印没有这样的周期)?
(如果存在循环,则输出应该是作为循环一部分的顶点列表。)
我知道如何找到O(n)
的复杂性的循环,互联网上也有gudies
我的问题是如何打印它。
这就是我试图做的事情:
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);
}
}
请记住它必须是O(n)
我的PrintCycle函数不打印所有顶点。
我需要一些帮助来打印我找到的循环的顶点。
答案 0 :(得分:5)
我注意到你的算法中有两件似乎不正确的事情。首先,当您使用DFS步行时,您应该保持以下不变量:
Visit()
尚未结束的访问顶点应该涂成灰色; Visit()
返回的已访问顶点应涂成黑色(或颜色,灰色或白色除外)。我注意到的另一件事是,你没有正确地为父节点分配节点。在你的Visit()
方法中,即使我们想要在下一步中访问的顶点是灰色的,即已经在DFS树中有父节点,也会分配父节点。
所以我会相应地更改你的代码:
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);
}
}
编辑:将PrintCycle
方法转换为非递归方法可能是个好主意:
PrintCycle(Vertex v, Vertex u)
{
do {
print u;
u = p[u];
} while (u != v);
}
答案 1 :(得分:0)
在递归搜索中,您可以添加一个参数,该参数是祖先的链,一直到搜索根。循环将由当前节点和链中的那些节点组成,这些节点在找到循环的灰色节点处结束。
通过链我的意思是一个lisp风格的列表:一对由一个节点和另一对组成,最后一对是空的。
更简单的方法是使用显式堆栈而不是递归进行搜索。堆栈上的节点都是灰色的。当您发现灰色节点指示循环时,可以通过堆栈向后工作来打印循环。