我读了一篇关于在有向图中找到一个循环的讨论here。现在,OP声称我们需要验证两个的东西:
u
到v
v
在递归堆栈中为什么我们需要第二次测试?你能举例说明它的必要性吗?
答案 0 :(得分:1)
答案 1 :(得分:1)
好吧,你可能会对有向图中后沿的定义和无向图中的后沿感到困惑。是的,他们是不同的。
在无向图中,后边是从当前顶点到已经访问过的顶点的边。 (作为你提到的链接的OP) 在有向图中,后边缘的定义是不同的。有向图中的后沿是从当前顶点到GRAY顶点的边(该顶点的DFS已经开始但尚未完成),这意味着它仍然在递归堆栈中。
因此,如果您在有向图中采用后边缘的定义,那么是的,它足以检测周期。
但是如果你在后向边缘中定义后边缘,那么你还需要确保v
在递归堆栈中以便检测一个循环。
示例:强>
将DFS访问顺序视为A -> B -> C
在此示例中,边<A,C>
是已显示图中的后边缘(因为C已被访问过)。
但它不是这个有向图中的后沿 - 已经访问过C但不在递归堆栈中,这意味着它不是一个循环。
答案 2 :(得分:1)
当它是交叉边而不是后边缘时,需要进行第二次测试。交叉边缘指的是从一个顶点到已经访问过的一个边缘的边缘,而与位置无关。 后边缘指的是指向起始顶点的祖先的边,一个仍然在递归堆栈中的边。就问题的提问方式而言,OP将后边缘称为指向另一个已访问边缘的边缘,但更准确的解释是交叉边缘。知道它是一个后沿是足够的,因为它意味着第二步。当第一个是交叉边缘时需要这些步骤,因为第二个证明交叉边缘是后边缘。在有向图中,交叉边缘并不总是意味着发生了循环。这是一个例子:
vertices a,b,c,d
a->b
a->c
b->d
d->c
根据处理此顺序,d->c
可视为交叉边缘,因此检测循环需要步骤2。不幸的是,后边缘和交叉边缘经常混淆,造成这样的混乱。下面是另一个关于两者之间差异的描述的链接,Depth-First Search。