题目链接:The Suspects
很简单的一道并查集,关键在如果保存每个集合的元素个数和如何合并处理。
值得学习的一点:把当前集合的元素个数存在根节点上,每次合并的时候,对根节点进行操作即可。
应用归类:集合合并,判断两点是不是在同一个集合,查找某一个集合上的元素个数等。
代码
#include<stdio.h>
#define NN 30005
int n;
int bin[NN];
int cnt[NN]; // 保存当前根节点所在集合的元素个数
int find(int x){
int r = x;
while (bin[r] != r){
r = bin[r];
}
int y = x;
while (bin[y] != y){
/* 很早以前都是用三句话实现压缩,今天终于找到两句话搞定的方法了*/
y = bin[y];
bin[y] = r;
}
return r;
}
void merge(int x, int y){
int fx, fy;
fx = find(x);
fy = find(y);
if (fx != fy){
/*每次合并的时候,都将根节点指向0*/
if (fx == 0){
bin[fy] = fx;
cnt[fx] += cnt[fy];
}
else if (fy == 0){
bin[fx] = fy;
cnt[fy] += cnt[fx];
}
else{
bin[fx] = fy;
cnt[fy] += cnt[fx];
}
}
}
int main()
{
int n, m, i, num, cur, next;
while (scanf("%d%d", &n, &m) != EOF){
if (n == 0 && m == 0) break;
for (i = 0; i < n; i++){
bin[i] = i;
cnt[i] = 1;
}
while (m--){
scanf("%d%d", &num, &cur);
while (--num){
scanf("%d", &next);
merge(cur, next);
cur = next;
}
}
printf("%d\n", cnt[0]);
}
return 0;
}