【问题标题】:Detecting a cycle in a directed graph在有向图中检测循环
【发布时间】:2017-01-19 00:33:08
【问题描述】:

我在 SO 阅读了关于在有向图中找到循环的讨论 here。现在,OP 声称我们需要验证 件事:

  1. uv 有一个后沿
  2. v 在递归堆栈中

为什么我们需要第二次测试?你能举个例子来证明它的必要性吗?

【问题讨论】:

    标签: algorithm graph computer-science


    【解决方案1】:

    仅我们已经访问过v这一事实是不够的。它允许我们从uv,但不能从vu

    简单的图形反例:

    数字是遍历顺序。我们有一个从 4 到 3 的后沿,但我们没有任何循环。

    【讨论】:

      【解决方案2】:

      好吧,您可能对有向图中的后边的定义和无向图中的后边的定义感到困惑。是的,它们是不同的。

      无向图中,后边是从当前顶点到已经访问过的顶点的边。 (正如您提到的链接中的 OP)。
      有向图中,后边的定义是不同的。有向图中的后边是从当前顶点到灰色顶点的边(该顶点的 DFS 已经开始但尚未完成),这意味着它仍在递归堆栈中。

      因此,如果您在有向图中采用后边的定义,那么是的,它足以检测循环。
      但是,如果您将后边定义为无向图中的定义,那么您还需要确保 v 在递归堆栈中以检测循环。

      有关更多信息和示例,请参阅 thisthis

      示例:
      考虑 DFS 访问顺序为A -> B -> C
      在这个例子中,边 <A,C> 是下图中的后边(因为 C 已经被访问过)。
      但它不是这个有向图中的后边——C 已经被访问过但不在递归堆栈中,这意味着它不是一个循环。

      【讨论】:

      • 非常感谢!!
      【解决方案3】:

      当它是交叉边缘而不是后边缘时,需要进行第二次测试。交叉边是指从一个顶点到已经访问过的顶点的边,无论位置如何。 后边指的是指向起始顶点的祖先的边,该祖先仍在递归堆栈中。就如何提出问题而言,OP 将后边缘称为指向另一个已访问边缘的边缘,但更准确的解释是交叉边缘。知道它是一个后边缘就足够了,因为它意味着第二步。当第一个是交叉边缘时需要这些步骤,因为第二个证明交叉边缘是后边缘。在有向图中,交叉边并不总是意味着发生循环。这是一个例子:

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

      根据处理的顺序,d->c 可以被认为是交叉边缘,因此需要第 2 步来检测循环。不幸的是,后边缘和交叉边缘经常混淆,导致这样的混乱。这是一个链接到另一个描述两者之间差异的链接,Depth-First Search

      【讨论】:

      • 谢谢 D. Law。 !
      • 我现在知道混乱在哪里(后边缘与交叉边缘)
      • 实际上,交叉边缘并不是您混淆的唯一情况 - 前向边缘也是在无向图中它实际上是后向边缘的情况。在有向图中,您有 4 种类型的边:后向、前向、交叉和树。在无向图中,您只有后边和树边。
      猜你喜欢
      • 1970-01-01
      • 2016-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多