Files
python/TangDou/DisjointSetUnion/POJ1611_ByPathCompact.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

82 lines
1.9 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <bits/stdc++.h>
using namespace std;
const int N = 30001;
int sum[N]; //每个集合人数
int fa[N]; //并查集数组
/**
测试数据
100 4
2 1 2
5 10 13 11 12 14
2 0 1
2 99 2
200 2
1 5
5 1 2 3 4 5
1 0
0 0
答案:
4
1
1
*/
//要深入理解这个递归并压缩的过程
int find(int x) {
if (fa[x] != x) fa[x] = find(fa[x]);
return fa[x];
}
/*
//查询+带路径压缩(循环版本,非递归)
int find(int x) {
int k, j, r;
r = x;
while (r != fa[r]) r = fa[r]; //查找跟节点
//找到跟节点用r记录下
k = x;
while (fa[k] != r) //非递归路径压缩操作
{
j = fa[k]; //用j暂存parent[k]的父节点
fa[k] = r; //parent[x]指向跟节点
k = j; //k移到父节点
}
return r; //返回根节点的值
}*/
//合并并查集
void join(int a, int b) {
int x = find(a), y = find(b);
if (x != y) {
fa[y] = x;
//人数合并 路径压缩过程中,也是可以处理附带信息的,并非按秩的就好。
sum[x] += sum[y];
}
}
int n, m, K, x, y;
int main() {
while (cin >> n >> m) {
//输入为 0 0 结束
if (n == 0 && m == 0) return 0;
//初始化
for (int i = 0; i < n; i++) { //因为有0号学生所以数组遍历从0开始
fa[i] = i; //每个学生自己是自己的祖先
sum[i] = 1; //集合中总人数初始值是1
}
for (int i = 0; i < m; i++) {
cin >> k >> x;
k--;
while (k--) {
cin >> y;
join(x, y);
}
}
cout << sum[find(0)] << endl; //寻找0号学生相关集合的总人数
}
return 0;
}