Kosaraju算法

Kosaraju算法（也被称为Kosaraju–Sharir算法）是一个在线性时间内寻找一个有向图中的强连通分量的算法。阿尔佛雷德·艾侯，约翰·霍普克洛夫特和杰弗里·乌尔曼相信该算法来自S. Rao Kosaraju于1978年撰写的一篇未发表论文之中。米卡·夏尔也独立发现了该算法并于1981年将其发表。该算法巧妙地利用了一个定理：“一个图的反向图和原图具有一样的强连通分量”。

Java代码实现

public class KosarajuAlgorithm {
    private boolean[] marked;
    private int[] id;
    private int count=-1;
    private Stack<Integer> reversePostOrder;
    public KosarajuAlgorithm(Digraph G){
        //G.V()返回有向图G的边数
        marked=new boolean[G.V()];
        id=new int[G.V()];
        //G.reverse()返回的为G的反向图
        Digraph G_reverse=G.reverse();
        //本遍循环是将G的反向图的逆后序排列存储在reversePostOrder中
        for(int i=0;i<G_reverse.V();i++){
            if(!marked[i]){
                dfs(G_reverse,i);
            }
        }
        count=0;
        //按照G的反向图的逆后排序进行深度优先搜索
        for(int i:reversePostOrder){
            if(!marked[i]){
                dfs(G,i);
                count++;
            }
        }
    }
    //深度优先搜索
    public void dfs(Digraph G,int v){
        marked[v]=true;
        id[v]=count;
        for(int i:G.adj(v)){
            if(!marked[i]){
                dfs(G,i);
            }
        }
        reversePostOrder.push(v);
    }}

复杂度

当图是使用邻接表形式组建的，Kosaraju算法需要对整张图进行了两次的完整的访问，每次访问与顶点数和边数之和成正比，所以可以在线性时间内访问完成。该算法在实际操作中要比Tarjan算法和基于路径的强连通分量算法要慢，这两种算法都只需要对图进行一次完整的访问。
当图是使用邻接矩阵形式组建的，算法的时间复杂度为。