【alg4-有向图】Kosaraju算法(计算强连通分量)

有向图中的强连通性

定义:如果两个顶点v和w是互相可达的,则称它们为强连通的。也就是说,既存在一条从v到w的有向路径,也存在一条从w到v的有向路径。如果从一幅有向图中的任意两个顶点都是强连通的,则称这幅有向图也是强连通的。

两个顶点是强连通的当且仅当它们都在一个普通的有向环中。

强连通分量

和无向图中的连通性一样,有向图中的强连通性也是一种顶点之间的等价关系,因为它有着以下性质:

  • 自反性:任意顶点v和自己都是强连通的。
  • 对称性:如果v和w是强连通的,那么w和v也是强连通的。
  • 传递性:如果v和w是强连通的且w和x也是强连通的,那么v和x也是强连通的。

作为一种等价关系,强连通性将所有顶点分为了一些等价类,每个等价类都是由相互均为强连通的顶点的最大子集组成的,我们将这些子集称为强连通分量

一个含有V个顶点的有向图含有1~V个强连通分量,一个强连通图只含有一个强连通分量,而一个有向无环图中则含有V个强连通分量。

Kosaraju算法

命题:使用深度优先搜索查找给定有向图的反向图,根据由此得到的所有顶点的逆后序再次用深度优先搜索处理有向图,其构造函数中的每一次递归调用所标记的顶点都在同一个强连通分量之中。

代码

其中DepthFirstOrder

package section4_2;

public class KosarajuSCC {

    private boolean[] marked;
    private int[] id;
    private int count;

    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) {
        int[][] data = {
                {4,2},
                {2,3},
                {3,2},
                {6,0},
                {0,1},
                {2,0},
                {11,12},
                {12,9},
                {9,10},
                {9,11},
                {8,9},
                {10,12},
                {11,4},
                {4,3},
                {3,5},
                {7,8},
                {8,7},
                {5,4},
                {0,5},
                {6,4},
                {6,9},
                {7,6}
        };
        int vn = 13;
        int en = 22;
        Digraph digraph = new Digraph(vn,en,data);

        KosarajuSCC scc = new KosarajuSCC(digraph);
        System.out.println(scc.count());
        System.out.println(scc.id(1));
        System.out.println(scc.id(2));
        System.out.println(scc.id(9));
        System.out.println(scc.id(6));
        System.out.println(scc.id(8));
    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值