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;
}