码迷,mamicode.com
首页 > 编程语言 > 详细

算法导论——Kosaraju算法(强连通性)

时间:2015-05-25 01:03:13      阅读:251      评论:0      收藏:0      [点我收藏+]

标签:

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




算法导论——Kosaraju算法(强连通性)

标签:

原文地址:http://my.oschina.net/u/1378920/blog/419365

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!