package org.loda.graph; import org.loda.util.In; /** * * @ClassName: KosarajuSCC * @Description: Kosaraju强连通算法 * * 理解:原图g,逆后序order中如果a->b,那么反向图rg中如果也有a->b,表示这是强连通的。 * 在反向图中按照原图的逆后序顺序进行dfs的时候,如果能够从a搜到b,那么必然有a->b,这部分必然强连通。并且 * 扩展开来,一次dfs能搜到多少,就表示有这个强连通分量有多大,总共要搜几次就代表一共有多少个强连通分量 * * @author minjun * @date 2015年5月24日 下午11:31:05 * */ public class KosarajuSCC { //强连通数 private int count; //是否被访问 private boolean[] visited; //每个元素所属的强连通分量id private int[] id; public KosarajuSCC(Digraph g){ //初始化 int v=g.v(); visited=new boolean[v]; id=new int[v]; //获取逆后序 DeptFirstOrder d=new DeptFirstOrder(g); //获取g的反向图 Digraph rg=g.reverse(); //根据反向图的拓扑顺序进行dfs for(int i:d.reversePost()){ if(!visited[i]){ dfs(i,rg); //每完成一次dfs,表示搜到一次强连通分量,count+1 count++; } } } /** * * @Title: dfs * @Description: 深度优先搜索 * @param @param v * @param @param g 设定文件 * @return void 返回类型 * @throws */ private void dfs(int v, Digraph g) { visited[v]=true; id[v]=count; for(int w:g.adj(v)){ if(!visited[w]){ dfs(w, g); } } } /** * * @Title: count * @Description: 强连通分量数量 * @param @return 设定文件 * @return int 返回类型 * @throws */ public int count(){ return count; } /** * * @Title: strongConnected * @Description: 判断两点是否强连通 * @param @param a * @param @param b * @param @return 设定文件 * @return boolean 返回类型 * @throws */ public boolean strongConnected(int a,int b){ return id[a]==id[b]; } /** * * @Title: id * @Description: 所属强连通分量的标识 * @param @param a * @param @return 设定文件 * @return int 返回类型 * @throws */ public int id(int a){ return id[a]; } /** * * @Title: printSCC * @Description: 打印所有的强连通分量 * @param 设定文件 * @return void 返回类型 * @throws */ public void printSCC(){ StringBuilder[] sb=new StringBuilder[count]; for(int i=0;i<sb.length;i++){ sb[i]=new StringBuilder(); } for(int i=0;i<id.length;i++){ sb[id[i]].append("\t"+i); } for(StringBuilder s:sb){ System.out.println("连通分量:"+s.toString()); } } public static void main(String[] args) { Digraph d=new Digraph(new In("F:\\算法\\attach\\tinyDG.txt")); KosarajuSCC k=new KosarajuSCC(d); System.out.println("强连通分量数量为:"+k.count()); //打印强所有连通分量 k.printSCC(); } }
引入的文本数据为:
13
22
4 2
2 3
3 2
6 0
0 1
2 0
11 12
12 9
9 10
9 11
7 9
10 12
11 4
4 3
3 5
6 8
8 6
5 4
0 5
6 4
6 9
7 6
---------------------华丽的分割线------------------
输出内容:
强连通分量数量为:5 连通分量: 7 连通分量: 6 8 连通分量: 9 10 11 12 连通分量: 0 2 3 4 5 连通分量: 1
时间: 2024-10-10 07:48:47