Algorithms IV求解强连通分量 Kosaraju算法

Posted stackupdown

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Algorithms IV求解强连通分量 Kosaraju算法相关的知识,希望对你有一定的参考价值。

【Algorithms IV】求解强连通分量 Kosaraju算法


Kosaraju
算法(也被称为Kosaraju–Sharir算法)是一个在线性时间内寻找一个有向图中的强连通分量的算法。

这个拗口的名字来自他的作者,但是查不到他的生平。应该是个印度人。

求解问题:要求有向图中的强连通分量的个数/划分

算法步骤:

 

即:

    对输入G, 反转边获得逆向图GR

    用DFS算法对图遍历得到reversePost序列(遍历图后push 到一个stack里,之后stack逆序弹出)

    依次对reversePost的未访问节点进行dfs, 一次dfs访问过的所有节点在一个强联通分量里。

 

    当图是使用邻接表形式组建的,Kosaraju算法需要对整张图进行了两次的完整的访问,每次访问与顶点数 V和边数 E之和 V+E成正比,所以O(V+E)内访问完成。

 

算法用到的定理:

 一个图的反向图和原图具有一样的强连通分量。

    一个图的reversePost的压入顺序是它的拓扑排序当且仅当它是DAG。

 

代码 (in JAVA):

 

KosarajuSCC.java
public class KosarajuSCC {
    private boolean[] marked; // reached vertices
    private int[] id; // component identifiers
    private int count; // number of strong components

    public KosarajuSCC(Digraph G) {
        marked = new boolean[G.V()];
        id = new int[G.V()];

        DepthFirstOrder order = new DepthFirstOrder(G.reverse());
        for (int s : order.reversePost()) {
            if (!marked[s]) {
                dfs(G, s);
                count++;
            }
        }
    }

    private void dfs(Digraph G, int v) {
        marked[v] = true;
        id[v] = count;
        for (int w : G.adj(v))
            if (!marked[w])
                dfs(G, w);
    }

    public boolean stronglyConnected(int v, int w) {
        return id[v] == id[w];
    }

    public int id(int v) {
        return id[v];
    }

    public int count() {
        return count;
    }

    public static void main(String args[]) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            int N = in.nextInt();
            Digraph G = new Digraph(N);
            int E = in.nextInt();
            for (int i = 0; i < E; i++) {
                int p = in.nextInt();
                int q = in.nextInt();
                G.addEdge(p, q);
            }
            KosarajuSCC kj = new KosarajuSCC(G);
            log("" + kj.count());
        }
    }

    private static void log(String count2) {
        System.out.println(count2);
    }
}

 

References

http://blog.csdn.net/dm_vincent/article/details/8554244

https://algs4.cs.princeton.edu/code/edu/princeton/cs/algs4/KosarajuSharirSCC.java.html

以上是关于Algorithms IV求解强连通分量 Kosaraju算法的主要内容,如果未能解决你的问题,请参考以下文章

有向图强连通分量求解

笔记:Tarjan算法 求解有向图强连通分量的线性时间的算法

Kosaraju算法解析: 求解图的强连通分量

tarjan算法(强连通分量 + 强连通分量缩点 + 桥 + 割点 + LCA)

关于强连通分量浅谈

Tarjan算法学习笔记