Kosaraju
算法,也称为 Kosaraju-Sharir
算法:在线性时间内找到有向图的强连通分量。
强连通分量
如果两个顶点 v
和 w
是相互可达的,则称为它们为强连通的。强连通性将所有顶点分为一些平等的部分,每个部分都是由相互均为强连通的顶点的最大子集组成的;我们称这些最大子集为强连通分量。
强连通分量是基于顶点而不是边的,可以认为 V
个顶点的有向图,可能含有 1 ~ V
个强连通分量。一个强连通图,只含有一个强连通分量;一个有向无环图则含有 V
个强连通分量。
强连通分量,必定存在环中。
算法定义
强连通分量的 Kosaraju
算法,使用深度优先 DFS
实现:
- 在给定的有向图
G
中,计算反向图的顶点逆后序排序 - 按照上一步逆后序中顶点的顺序,在
G
中按照深度优先搜索访问未被标记的顶点 - 所有在同一个递归
DFS
调用中被访问到的顶点都在同一个强连通分量中
这里逆后序排序,不是拓扑排序,虽然算法类似,但是拓扑排序针对的是有向无环图,DFS
中会判断是否存在环,检测到环直接退出;而逆后序不检测环,会遍历所有顶点。
动画演示
动画演示和标准的 Kosaraju
算法有点不一样:它是先 DFS
遍历顶点得到逆后序排序,然后再将有向图置为反向图,按照逆后序排序取出顶点,深度优先搜索反向图。结果和 Kosaraju
算法一致。
算法实现
算法解析:
marked[]
数组
记录当前顶点是否被访问过。count
记录有多少个强连通分量。id[]
数组
记录当前顶点属于第几个强连通分量。G.reverse()
有向图G
的反向图:即将所有边的指向全部反过来。ReversePostSort.getSort
使用深度优先搜索获取顶点的逆后序排序。
1 | // Kosaraju-Sharir 强连通分量算法 |
小结
- 时间复杂度
时间复杂度为O(V+E)
。