Kosaraju算法中的步骤顺序

时间:2014-05-31 03:37:35

标签: algorithm data-structures graph computer-science kosaraju-sharir

Kosaraju-Sharir算法的Wikipedia summary如下:

  

设G是有向图,S是空堆栈。

     
      
  • 虽然S不包含所有顶点。   
        
    • 选择不在S中的任意顶点v。
    •   
    • 从v开始执行深度优先搜索。每次深度优先搜索完成扩展顶点u时,将u推到S上。
    •   
  •   
  • 反转所有弧的方向以获得转置图。
  •   
  • 虽然S是非空的:   
        
    • 从S
    • 弹出顶部顶点v   
    • 在转置图中从v开始执行深度优先搜索。
    •   
    • 访问顶点集将给出包含v的强连通分量;记录这个并从图G和堆栈S中删除所有这些顶点。等效地,可以使用广度优先搜索(BFS)代替深度优先搜索。
    •   
  •   

但在我的教科书--Sedgewick的Algorithms (fourth edition)中 - 它描述了算法的步骤如下:

  
      
  • 给出有向图G,计算其反向图的反向后序。 ģ - [R
  •   
  • 在G上运行标准DFS,但考虑刚刚计算的顺序中未标记的顶点而不是标准的数字顺序
  •   
  • 所有顶点的集合......
  •   

在最后一步中得出的结论是相同的,在它之前的操作中执行的操作也是相同的 - 但似乎这些操作以不同的顺序给出:维基百科告诉我首先在G上执行DFS并且然后转置它,在G R 上做第二个DFS,而我的教科书建议我从转置开始,在G R 上做第一个DFS并且第二个关于G.

我的主要问题是:我是否正确理解了这一点,还是我误解了其中一个人在说什么?

其次:直观地说,似乎这些操作是传递性的,因此这两种"不同的方法"实际上是等价的,并且总会产生相同的最终结果。我已经在几个有向图上测试了这种直觉,它似乎也适用 - 但它是吗?

第三:假设是,是否有任何客观理由偏爱另一方,或者仅仅是偏好问题?

1 个答案:

答案 0 :(得分:2)

IMO这两种算法是等价的,但存在细微差别。不同之处在于SCC(强连接组件)输出的顺序。

假设我们有一个非循环的图表,SCC按顺序排列为S1,S2,S3,S4。

S1 -> S2 -> S3 -> S4

算法1(维基百科)。

当你构建堆栈S时,对于任何顶点v,v之后的所有顶点都应该进入v之前的堆栈S,因为我们正在前向图上执行DFS。

现在我们反转图表:

R_S1 <- R_S2 <- R_S3 <- R_S4

要从堆栈S中弹出的第一个顶点应位于R_S1中。因此,当您执行DFS时,要输出的第一个SCC应为R_S1

算法2(书)。

这里我们首先反转图表:

R_S1 <- R_S2 <- R_S3 <- R_S4

现在当我们在任何顶点v上进行DFS时,v之前的顶点(在原始图中)应该在v之前有序。此外,因为我们开始来自N的order_index然后递减order_index,v之后的所有顶点的拓扑排序都应低于v。

原图:

S1 -> S2 -> S3 -> S4

最低有序顶点现在应在S4。因此,从图中输出的第一个SCC应为S4,而不是第一种情况下的R_S1