一、理解与感悟
并查集+附加信息,附加信息为家族中成员的数量,需要一个额外的数组(s[N])记录以结点(i)为根的的家族成员数量。
与最祼并查集的区别:
-
初始化时需要将(s[i]=1)
-
合并时,需要(s[find(b)]+ =s[find(a)])
-
查询时:(s[find(a)])
二、实现代码
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int n, m;
int p[N]; //爸爸数组
int s[N]; //每一个集合中点的数量
//递归查找父节点
int find(int x) {
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
int main() {
//优化输入
ios::sync_with_stdio(false);
cin >> n >> m;
//并查集初始化
for (int i = 1; i <= n; i++) {
p[i] = i;
s[i] = 1; //每个家族的成员数:1
}
while (m--) {
string op;
int a, b;
cin >> op;
if (op[0] == 'C') {
cin >> a >> b;
//如果a和b已经在同一个集合里了,那么就不需要进行处理了
if (find(a) == find(b)) continue;
//如果a和b不在同一个集合中
s[find(b)] += s[find(a)];//更新族长记录的家族人员数量
p[find(a)] = find(b); //实现两个集合的合并
} else if (op[1] == '1') {
cin >> a >> b;
if (find(a) == find(b)) puts("Yes"); // 两个节点在一个集合里
else puts("No"); //不在一个集合里
} else {
//查询个数
cin >> a;
printf("%d
", s[find(a)]);
}
}
return 0;
}