只需要在并查集上加一个数组total保存根的总结点数就好
有两种途径:
1)在求父节点时,直接将子结点的total值全累加到根节点上
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=30000+5;
int p[maxn],total[maxn];
int getPar(int x){
if(p[x]==x) return x;
int p1=getPar(p[x]);
total[p1]+=total[x];
total[x]=0;
p[x]=p1;
return p1;
}
void merge(int a,int b){
int p1=getPar(a);
int p2=getPar(b);
if(p1==p2) return;
p[p1]=p2;
total[p2]+=total[p1];
total[p1]=0;
}
int main()
{
int n,m;
while(cin>>n>>m&&n)
{
for(int i=0;i<n;i++){
total[i]=1;
p[i]=i;
}
while(m--)
{
int t;
cin>>t;
int x;
cin>>x;t--;
while(t--)
{
int y;
cin>>y;
merge(y,x);
}
}
cout<<total[getPar(0)]<<endl;
}
return 0;
}
2)在合并时,直接两个父节点total值相加
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=30000+5;
int p[maxn],total[maxn];
int getPar(int x){
return p[x]==x?x:p[x]=getPar(p[x]);
}
void merge(int a,int b){
int p1=getPar(a);
int p2=getPar(b);
if(p1==p2) return;
total[p2]+=total[p1];
p[p1]=p2;
}
int main()
{
int n,m;
while(cin>>n>>m&&n)
{
for(int i=0;i<n;i++){
total[i]=1;
p[i]=i;
}
while(m--)
{
int t;
cin>>t;
int x;
cin>>x;t--;
while(t--)
{
int y;
cin>>y;
merge(y,x);
}
}
cout<<total[getPar(0)]<<endl;
}
return 0;
}