Kosaraju算法

Kosaraju算法也许最容易理解的一个算法是Kosaraju于80年代提出的,它执行两次DFS。第一次DFS得到了关于各个SCC拓扑顺序的有关信息,而第二次DFS按照这个拓扑顺序的逆序进行DFS,从而把每个SCC分开。
算法步骤如下:第一步调用\(DFS(G)\),计算出每个结点的\(f[u]\)或者\(post[u]\)第二步计算G的转置GT (即把所有有向边(u, v)变为有向边(v, u))第三步调用\(DFS(GT )\),在主循环中按照\(f[u]\)或者\(post[u]\)递减的顺序执行DFS-VISIT,则得到的每个DFS树恰好对于一个SCC。
算法的时间复杂度为\(O(n+m)\),但注意并不是在图的所有表示法中都很容易求出转置。
为什么算法是正确的呢?
我们首先证明以下定理:
定理:\(d(U)\)\(f(U)\)表示集合U所有元素的最早发现时间和最晚完成时间,则对于G中的两个SCC C和C',如果C到C'有边,则\(f(C)>f(C')\)。证明分两种情况。
情况一:\(d(C)<d(C')\)。考虑C中第一个被发现的点\(x\),则\(x\)被发现时\(C'\)全为白色。而\(C\)\(C'\)有边,故\(x\)\(C'\)中的每个点都有白色路径。这样,\(C\)的其他点和\(C'\)的所有点都是x的后代,因此\(f(C) > f(C')\)
情况二:\(d(C)>d(C')\)。由于从\(C'\)不可到达\(C\),所以必须等\(C'\)全部访问完毕后才能访问\(C\),因此\(f(C) > f(C')\)。作为定理的推论,如果GT 中\(C\)\(C'\)有边,则\(f(C)<f(C')\)。由于G和GT 的强连通分量完全一致,所以只需要在GT 中按照\(f\)值递减的顺序执行DFS-VISIT即可。可能有读者会认为不需要转置而直接在G中按照f递增的顺序执行DFS-VISIT也能奏效,但可惜这是错误的。对于G中的两个SCC \(C\)\(C'\),如果C到\(C'\)有边,刚才的定理说的是\(f(C)>f(C')\),其中二者取的是\(C\)\(C'\)\(f\)值的最大值,而并没有说\(C\)\(C'\)中最小的f值哪个大。如果按照f递增的顺序遍历,我们无法知道究竟会先遇到\(C\)中的点还是\(C'\)中的点。如果在GT 上操作,由推论知\(f(C)<f(C')\),所以当按\(f\)值降序考虑时一定会先遇到\(C'\)中的点,从而正确的把\(C\)\(C'\)分开。

转载于:https://www.cnblogs.com/Douglas-Zhou/p/Kosaraju.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值