为什么我们需要在Kosaraju算法的图形补充上运行DFS?

时间:2014-01-03 10:15:11

标签: algorithm depth-first-search kosaraju-algorithm

有一种着名的算法可以找到名为Kosaraju's algorithm的强连通组件,它使用两个DFS来解决这个问题,并在θ(|V| + |E|)时间内运行。

首先我们在图的补充(G R )上使用DFS来计算顶点逆向后序,然后我们在主要上应用第二个DFS图形G通过以反向顺序取顶点来计算强连通分量。

虽然我理解算法的机制,但我并没有得到反向后序的需要。

如何帮助第二个DFS找到强连接组件?

3 个答案:

答案 0 :(得分:2)

假设第一个DFS的结果是:

----------v1--------------v2-----------

其中“ - ”表示任何数字,强连接组件 g 中的所有顶点都出现在 v1 v2 之间。

按订单排序的DFS提供以下保证

  • v2 之后的所有顶点都不会指向反向图中的 g (也就是说,您无法从 g 到达这些顶点在原始图中)
  • v1 之前的所有顶点都不能从反向图中的 g 指向(也就是说,你无法从这些 g 到达原点图中的顶点)

总之,第一个DFS确保在第二个DFS中,先前访问过的强连接组件不能与其他未访问的强连接组件具有任何边缘点

一些详细说明

让我们简化图表如下:

  • 整个图表是G
  • G包含两个强连接组件,一个是 g ,另一个是单个顶点 v
  • v g 之间只有一条边,从 v g 或来自 g v ,此边缘的名称是 e
  • g' e'代表 g 的反面, e

此算法可能失败的情况可以推断为

  1. v 启动DFS, e' v 指向 g'
  2. g'内的顶点启动DFS, e' g'指向 v
  3. 对于情况1

    原点图表就像g-->v,反转图表看起来像g'<--v

    要从v开始第二个DFS,第一个DFS生成的发布顺序必须类似于

    g1, g2, g3, ..., v

    但是你很容易发现从 v 开始第一个DFS也不从 g'开始都可以给你这样的帖子顺序,所以在这种情况下,它是保证是第一个DFS,第二个DFS不会从一个顶点开始,而顶点都是一个强连接组件。

    对于情况2

    类似于情况1,在情境2中,原始图表为g<--v且反向开启为g'-->v,保证在之前访问 v g '中的任何顶点。

答案 1 :(得分:1)

  1. 当您第一次在图表上运行DFS时,对于您访问的每个节点,您都可以从该节点获得有关可访问的所有节点的知识(您可以在首先完成DFS)。

  2. 然后,当您反转所有顶点并再次运行DFS时,对于您访问的每个节点,您都可以了解可以到达的所有节点非倒置节点图表(再次,你在第二个DFS完成后得到这个信息)。

  3. 示例:假设您的第一个DFS到达节点X.从该节点“您可以看到”您可以访问的所有邻居。 (我希望这是可以理解的)。然后,假设您的第二个DFS到达该节点X,但这次所有顶点都被反转。如果然后从您的节点X“您可以看到”任何其他节点,则意味着在反转顶点之前,可以从您现在看到的所有邻居到达节点X.通过以正确的顺序调用第二个DFS,您可以获得每个节点X在两个DFS树中可以从X到达的所有节点(因此,对于每个节点X,您获得的节点都可以从X到达并且可以到达X - 根据定义,这些是紧密连接的组件。)

答案 2 :(得分:0)

假设列表L是节点的后DFS访问。 u->v表示存在从uv的转发路径。

如果u->v而非v->u,则u必须出现在vL处。但是,SCC中的节点,例如vw可以以任意顺序出现在列表L上。

Imgur

因此,如果节点x严格出现在列表y上的L之前:

  • 情况1:x->yy->x,就像vw的情况一样
  • 情况2:x->y而不是y->x,就像uv的情况一样
  • 情况3:不是x->y也不是y->x

Kosaraju的算法从左向右迭代L,并从转置图上的每个节点(边的方向相反)开始运行DFS。如果DFS可以到达某个节点并且该节点不属于任何SCC,则可以将该节点添加到当前根的SCC中。

在情况1中,我们将y添加到x的SCC中。在情况3中,yx位于不同的SCC中。

情况2需要特别注意。在我们从y调用DFS时,x已经在其他SCC中,因此我们不会将x添加到y的SCC中。想象一下,如果在从根y开始的DFS之前调用了从根x开始的DFS,那么x将被添加到y的SCC中,这是错误的。

简而言之,第一个DFS安排了从其{strong>上的y 可以到达但不能的那些节点左。因此,第二个DFS可以避免将这样的节点y添加到x的SCC中。