题目大意:有n个集合,提供三种操作
1 p q:将p所在的集合和q所在的集合并起来
2 p q:将p元素移到集合q所在的集合
3 p:求出p所在集合有多少个元素并输出这些元素的和
解题思路:第二种操作比较难,如果p是根的话,移动的话就比较难了
这里设置两个父亲节点,f[0]代表实父亲,f[1]代表虚父亲
然后在find的时候分两个情况进行合并
#include<cstdio>
#define maxn 100010
struct Node {
int f[2], num, sum;
}N[maxn];
void init(int n) {
for(int i = 0; i <= n; i++) {
N[i].f[0] = i;
N[i].f[1] = -1;
N[i].num = 1;
N[i].sum = i;
}
}
int find(int x) {
if(N[x].f[1] == -1) {
int t = N[x].f[0];
while(N[t].f[0] != t)
t = N[t].f[0];
int f = N[x].f[0];
while(f != t) {
int tmp = N[f].f[0];
N[f].f[0] = t;
f = tmp;
}
return t;
}
else {
int f = N[x].f[1];
while(N[f].f[0] != f)
f = N[f].f[0];
N[x].f[1] = f;
return f;
}
}
void Union() {
int p, q;
scanf("%d%d", &p, &q);
int fp = find(p);
int fq = find(q);
if(fp != fq) {
N[fp].f[0] = fq;
N[fq].num += N[fp].num;
N[fq].sum += N[fp].sum;
}
}
void Move() {
int p, q;
scanf("%d%d", &p, &q);
int fp = find(p);
int fq = find(q);
N[fp].num--, N[fp].sum -= p;
N[fq].num++, N[fq].sum += p;
N[p].f[1] = fq;
}
void Output() {
int p;
scanf("%d", &p);
int fp = find(p);
printf("%d %d\n", N[fp].num, N[fp].sum);
}
int main() {
int op, n, m;
while(scanf("%d%d", &n, &m) == 2) {
init(n);
while(m--) {
scanf("%d", &op);
switch(op) {
case 1: Union();break;
case 2: Move();break;
case 3: Output();
}
}
}
return 0;
}