并查集

并查集,顾名思义合并查找。时间一长有点记不清怎么写了,现在赶紧写下记录一下。。。。。

典型例题有:hdu1232 ,poj 2524 ,poj 1182, hdu 1213.

主要函数就两个find,union。

find用来查找他的祖先,union用来合并。

int finds(int x)//查找他的祖先
{
	int r=x;
	while(vis[r]!=r)
		r=vis[r];
	return r;
}


void unon(int a,int b)//合并祖先
{
	int aa=finds(a);
	int bb=finds(b);
	if(aa!=bb)
		vis[aa]=bb;
}

最重要的是先定义好祖先数组,让每个数字等于他自身,即自己是自己的祖先,开始根据所给关系查找,拿hdu1232举例:

#include<bits/stdc++.h>
using namespace std;
int vis[1005];
int finds(int x)//如果自己不是自己,返回自己的祖先值
{
	int r=x;
	while(vis[r]!=r)
		r=vis[r];
	return r;
}

void union(int a,int b)
{
	int aa=finds(a);//查找每个数字的祖先
	int bb=finds(b);
	if(aa!=bb)
		vis[aa]=bb;//祖先不同进行合并
}

int main()
{
	int n,m;
	while(~scanf("%d%d",&n,&m))
	{
		if(n==0)
			break;
			
		int a,b;
		
		for(int i=1;i<=n;i++)
			vis[i]=i;//将其自己赋值自己,开始自己是自己祖先 
			
		for(int i=0;i<m;i++)
		{
			scanf("%d%d",&a,&b);//输入关系进行查找
			union(a,b);
		}	
		
		int sum=0;
		for(int i=1;i<=n;i++)
		{
			if(vis[i]==i)//通过合并将所有关系打乱,只有vis[i]=I的表明自己是一个集合,要是其他集合的人,自身祖先数组会改变!!!!
				sum++;
		}
		
		cout<<sum-1<<endl;//题目求的是还剩几条
	}
	
return 0;
} 

例如测试数据

4 2

1 3

4 3

vis数组关系:

最后重要一点:要判断有几个集合通过循环查找自己与vis数组相同的,即vis[i]=i;有几个相等的就有几个集合,如果他和其他集合有关系,自身祖先数组vis会改变,不会是自己的!!!!!

再根据题意判断要求的结果!!!

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值