算法導論——Kosaraju算法(強連通性)

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
相關文章
相關標籤/搜索