就我所知,有三种时间复杂度为O(n)的方法可以求强连通分量,分别是Kosaraju、Tarjan和Gabow。
- Kosaraju
算法的步骤为- 对图G进行DFS,并按照遍历完成的先后顺序进行标号。
- 将图G中所有的边反向得到G'。
- 对G'进行DFS,每轮DFS都选择编号最大的点最为当前的遍历树的根。
- 最后,遍历得到的森林就是SCC的集合。
- Tarjan
第一个求解SCC的算法,应用非常广泛,几乎任何和图的遍历有关的问题都可以套用Tarjan算法的思想(比如,求割点、桥、块等等)。
在遍历时,对每一个节点定义时间戳,同时定义Low函数,含义为节点及其子孙通过非父子边的返祖边所能到达的最小时间戳。最后若Low函数等于其时间戳,则当前递归栈内存在一个SCC。
代码如下: