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