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(); } }
引入的文本數據爲: java
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
算法
---------------------華麗的分割線------------------ app
輸出內容: ui
強連通份量數量爲:5 連通份量: 7 連通份量: 6 8 連通份量: 9 10 11 12 連通份量: 0 2 3 4 5 連通份量: 1