并查集专题

1、求一个集合内的元素个数

模板题链接:poj1611

其方法是初始化一个数组全为1,用来记录每个集合内的元素个数,每当发生合并的时候,祖先集合元素个数+=被合并的元素个数,从而完成元素个数的更新

//求一个集合内元素个数 
#include<bits/stdc++.h> 
const int maxn = 35000;
const int inf = 0x3f3f3f3f;
int n,m,k;
int pre[maxn];
int num[maxn];//记录每个组内有多少人 
void init(){
	for(int i=0;i<=n;i++){
		pre[i]=i;//初始化每个集合都为自己 
		num[i]=1;//初始化每个集合都只有一个人 
	}
}
int find(int x){
	if(x==pre[x])
		return x;
	return pre[x]=find(pre[x]);
}
void join(int x,int y){
	int fx=find(x);
	int fy=find(y);
	
	if(fx==fy)//如果自己就是自己的祖先,直接返回 
		return; 
	pre[fy]=fx;//否则让fx当fy的祖先,也就是合并节点
	num[fx]+=num[fy];//同时增加集合内元素个数 
}
int main()
{
	while(scanf("%d%d",&n,&m)!=EOF){
		if(n==0&&m==0)break;
		init();
		for(int i=1;i<=m;i++){
			scanf("%d",&k);
			int x,y;
			scanf("%d",&x);
			for(int j=1;j<=k-1;j++){
				scanf("%d",&y);
				join(x,y);
			}
		}
		int ans=num[find(0)];//因为0不一定是祖先,所以要find一下 
		printf("%d\n",ans); 
	}
	return 0;
}

2、求集合个数

模板题链接:HDU1213

连数组都不需要,只需设置一个变量ans=0记录集合个数,然后遍历每个点,如果这个点祖先==自己,说明它是根,ans++

核心代码:if(find(i)==i)ans++;

//求一个集合内元素个数 
#include<stdio.h>
const int maxn = 35000;
const int inf = 0x3f3f3f3f;
int T;
int pre[maxn];
int n,m;
void init(){
	for(int i=0;i<=1005;i++){
		pre[i]=i;
	}
}
int find(int x){
	if(x==pre[x])
		return x;
	return pre[x]=find(pre[x]);
}
void join(int x,int y){
	int fx=find(x);
	int fy=find(y);
	
	if(fx==fy)	
		return;
	pre[fy]=fx;
}
int main()
{
	scanf("%d",&T);
	while(T--){
		init();
		scanf("%d%d",&n,&m);
		for(int i=1;i<=m;i++){
			int x,y;
			scanf("%d%d",&x,&y);
			join(x,y);
		}
		int ans=0;
		for(int i=1;i<=n;i++){
			if(find(i)==i)ans++;//遍历每个点,如果这个点是祖先,也就是根节点,则集合个数++ 
		}
		printf("%d\n",ans);
		
	}
	return 0;
}

相关题目

团体天梯赛L2-007 家庭房产

团体天梯赛L2-010 排座位

团体天梯赛L2-024 部落

团体天梯赛L3-003 社交集群

Codeforces 1131 F.Asya And Kittens            题解

猜你喜欢

转载自blog.csdn.net/zsnowwolfy/article/details/87188452
今日推荐