简体   繁体   English

在有向图中检测周期

[英]Detecting a cycle in a directed graph

I read a discussion here , at SO about finding a cycle in a directed graph. 在这里阅读了关于在有向图中找到循环的讨论。 Now, the OP claims that we need to validate two things: 现在,OP声称我们需要验证件事:

  1. There's a back edge from u to v uv有一个后沿
  2. v is in the recursion-stack v在递归堆栈中

Why do we need the second test? 为什么我们需要第二次测试? Could you give an example to demonstrate it's necessity? 您能举个例子证明它的必要性吗?

Only the fact that we already visited v is not sufficient. 仅我们已经访问v的事实是不够的。 It allows us to go from u to v , but not from v to u . 它允许我们从u转到v ,但不能从v转到u

Simple graphical counterexample: 简单的图形反例:

反

Numbers are traversal order. 数字是遍历顺序。 We have a back edge from 4 to 3, but we don't have any cycles. 我们的后缘为4到3,但没有任何循环。

Well, you probably got confused between the definition of a back-edge in a directed graph and a back-edge in an undirected graph. 好吧,您可能对有向图中的后沿定义和无向图中的后沿定义感到困惑。 Yes, they are different. 是的,它们是不同的。

While in undirected graph back edges are edges from the current vertex to an-already-visited vertex. 无向图中,后边缘是从当前顶点到已访问的顶点的边缘。 (as OP from your link mentioned). (如您提到的链接中的OP)。
In directed graph the definition for back edge is different. 在有向图中,后边缘的定义不同。 A back edge in a directed graph is an edge from current vertex to a GREY vertex (the DFS for this vertex has started but not yet finished), meaning it is still in the recursion stack. 有向图的后边缘是从当前顶点到GREY顶点的边缘(此顶点的DFS已开始但尚未完成),这意味着它仍在递归堆栈中。

So if you take the definition of a back edge as it is in a directed graph then yes, it is enough for detecting a cycle. 因此,如果按照有向图中的方式定义后沿,则可以,它足以检测周期。
But if you take the definition of a back edge as it is in an undirected graph then you will need also to make sure that v is in the recursion stack in order to detect a cycle. 但是,如果您将后缘的定义定义为无向图中,那么您还需要确保v在递归堆栈中以检测循环。

See this and this for more information and examples. 这个这个以获取更多信息和示例。

Example: 例:
Consider the DFS visit order to be A -> B -> C . 考虑DFS访问顺序为A -> B -> C
In this example, the edge <A,C> is a back edge in the undericted graph (as C was already visited). 在此示例中,边<A,C>是带下划线的图中的后边(因为C已被访问)。
But it is not a back edge in this directed graph - C was already visited but is not in the recursion stack, meaning it is not a cycle. 但这不是该有向图的后边缘-C已被访问但不在递归堆栈中,这意味着它不是循环。 在此处输入图片说明

The second test is needed when it is a cross edge , not a back edge. 当它是交叉边缘而不是后边缘时,需要进行第二次测试。 A cross edge refers to an edge that goes from one vertex to an already visited one regardless of position. 交叉边缘是指从一个顶点到一个已经访问过的顶点的一个边缘,与位置无关。 A back edge refers to an edge that points to an ancestor of the starting vertex, one that is still in the recursive stack. 后边缘指的是指向起始顶点的祖先的一条边,该顶点仍在递归堆栈中。 In terms of how the question was asked, the OP refers to a back edge as an edge that points to another already visited edge, but a more accurate explanation would be a cross edge. 就如何提出问题而言,OP将后边缘称为指向另一个已经访问过的边缘的边缘,但是更准确的解释是交叉边缘。 Knowing it is a back edge is sufficient because it implies the second step. 知道它是后边缘就足够了,因为这意味着第二步。 Those steps are required when the first is a cross edge because the second proves the cross edge is a back edge. 当第一个是交叉边缘时,需要执行这些步骤,因为第二个步骤证明了交叉边缘是后边缘。 In a directed graph, a cross edge does not always mean that a loop occurs. 在有向图中,交叉边缘并不总是意味着发生循环。 Here is an example: 这是一个例子:

vertices a,b,c,d
a->b
a->c
b->d
d->c

Depending on the order that this is processed, d->c can be considered a cross edge, therefore step number 2 would be required to detect a loop. 根据处理顺序,可以将d->c视为交叉边缘,因此需要步骤2来检测循环。 Unfortunately, back edge and cross edge are mixed up quite often causing confusion like this. 不幸的是,后边缘和交叉边缘经常混合在一起,从而引起混乱。 Heres a link to another description of the difference between the two, Depth-First Search . 这是指向两者之间差异的另一描述的链接,即深度优先搜索

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM