无向图的连通性问题(并查集)

先不要看我的整理,看一位大牛的文章,你就不用再看我写的了。
http://blog.csdn.net/dellaserss/article/details/7724401/
真的很厉害吧!用江湖来讲解一个算法,真的是绝妙的。我觉得学算法就是需要这样的生动有趣,很多人看见算法因为其专业的描述十分枯燥而变得十分头疼。如果能有生动形象的语言来描述它,就会令人兴趣大增。

它的思想就是:如果两个顶点a和b有一条路径相连,那么a的父顶点设为b,以此类推,b的父顶点c,如果连通,最后一个点的父顶点就是它本身。如果有其他顶点的父顶点是它本身,那么这样的图就不是连通的。

比如举个例子
无向图的连通性问题(并查集)_第1张图片
输入边分别为:(0 , 1) , (0 , 2) , (0 , 3) , (1 , 3)
先初始化,每个点刚开始是独立为一个集合,它的父顶点就是自己。即pre[0] = 0 , pre[1] = 1 , pre[2] = 2 pre[3] = 3
接下来进行并查集:

  1. 查询0和1这两个点的父顶点,发现都为本身,返回父顶点 0和1,如果这两个父顶点不相等,则将两个集合合并,即pre[0] = 1,那么0的父节点就变成了1,这样0到1就有了一条路径。
  2. 查询0和2这两个点的父顶点,发现0的父顶点是1,而2的父顶点是本身2,则将两个集合合并,即pre[1] = 2,那么0和1的父顶点变成了2,这样1到2就有一条路径
  3. 查询0和3这两个点的父顶点,发现0的父顶点为2,而3的父顶点是本身,则将两个集合合并,即pre[2] = 3,那么0和1和2的父顶点变成了3,这样2到3就有一条路径。
  4. 查询1和3这两个点的父顶点,发现1的父顶点就是3,那么便不用合并集合了。

代码如下:

#include
#include
using namespace std;
const int maxn = 1000+10;
int V,E;
int pre[maxn];

/*初始化*/ 
void init()
{
	for(int i=1; i<=V; i++)
	{
		pre[i] = i;
	}
}

/*查找根节点*/
int find(int x)
{
	int r = x;
	while(r!=pre[r])
	r = pre[r];
	
	int i = x;//路径压缩 
	int j;  
	while(i != r)
	{
		j = pre[i];
		pre[i] = r;
		i = j;
	}
	return r;
}

int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&V,&E);
		init();
		int s,t;
		for(int i=0;i

效果图:
无向图的连通性问题(并查集)_第2张图片

你可能感兴趣的:(并查集,图的连通性)