题目:
#include<iostream>
using namespace std;
const int N=30001;
int father[N]; //记录根节点
int weight[N]; //记录所在组的人数
void init(int n){
for(int i=0;i<n;i++){
father[i]=i;
weight[i]=1;
}
}
int find(int x)
{
if(father[x]==x) return x;
father[x]=find(father[x]);
return father[x];
}
void merge(int a, int b)
{
int roota=find(a),rootb=find(b);
if(roota!=rootb){
father[rootb]=roota;
weight[roota]+=weight[rootb];
}
}
int main()
{
int n,m;
while(1){
scanf("%d%d",&n,&m);
if(!n&&!m) break;
init(n);
for(int j=0;j<m;j++){
int k,x,y;
scanf("%d%d",&k,&x);
for(int i=1;i<k;i++){
scanf("%d",&y);
merge(x,y);
}
}
printf("%d\n",weight[find(0)]);
}
return 0;
}
并查集四部曲:
①确定father和weight数组含义:
int father[N]; //记录根节点
int weight[N]; //记录所在组的人数
②初始化:
father[i]=i;
weight[i]=1;
③确定路径压缩方式:
father[x]=find(father[x]);
④确定合并方式:
father[rootb]=roota;
weight[roota]+=weight[rootb];
关键:
不断地合并组,最后0所在的组的人数就是嫌疑人数。