initial:
cpp
void initial(int n) {
for (int i = 0; i < n; i++) {
p[i] = i;
h[i] = 1;
}
}
find:
cpp
int find(int x) {
if (p[x] == x) return x;
else return p[x] = find(p[x]);
}
union:
cpp
void union(int x, int y) {
int rootx = find(x);
int rooty = find(y);
if (rootx != rooty) {
if (h[rootx] < h[rooty]) p[rootx] = rooty;
else if (h[rootx] > h[rooty]) p[rooty] = rootx;
else p[rootx] = rooty, h[rooty]++;
}
}
例题:

cpp
#include <iostream>
using namespace std;
const int N = 10010;
int p[N], h[N];
bool visited[N]; // 记录鸟是否出现过
bool isroot[N]; // 记录某个根节点是否已被计入树
int photos[10000][10]; // 每张照片中最多10只鸟,最多10000张照片
int photosize[10000]; // 每张照片的鸟的数量
void initial(int n) {
for (int i = 0; i < n; i++) {
p[i] = i;
h[i] = 1;
visited[i] = false;
isroot[i] = false;
}
}
int find(int x) {
if (p[x] == x) return x;
else return p[x] = find(p[x]);
}
void unionset(int x, int y) {
int rootx = find(x);
int rooty = find(y);
if (rootx != rooty) {
if (h[rootx] < h[rooty]) p[rootx] = rooty;
else if (h[rootx] > h[rooty]) p[rooty] = rootx;
else p[rootx] = rooty, h[rooty]++;
}
}
int main() {
int n;
cin >> n;
initial(N);
int maxid = 0;
// 输入照片数据
for (int i = 0; i < n; i++) {
int k;
cin >> k;
photosize[i] = k;
for (int j = 0; j < k; j++) {
int bird;
cin >> bird;
photos[i][j] = bird;
visited[bird] = true;
if (bird > maxid) maxid = bird;
}
}
// 合并同一张照片的鸟
for (int i = 0; i < n; i++) {
int k = photosize[i];
for (int j = 1; j < k; j++) {
unionset(photos[i][0], photos[i][j]);
}
}
int birdcnt = 0, treecnt = 0;
// 统计鸟的数量和树的数量(去重根节点)
for (int i = 1; i <= maxid; i++) {
if (visited[i]) {
birdcnt++;
int root = find(i);
if (!isroot[root]) {
isroot[root] = true;
treecnt++;
}
}
}
cout << treecnt << " " << birdcnt << endl;
// 处理查询
int q;
cin >> q;
while (q--) {
int x, y;
cin >> x >> y;
if (find(x) == find(y)) cout << "Yes" << endl;
else cout << "No" << endl;
}
return 0;
}