并查集的话,找到一个节点是无法访问他的儿子的,所以如果将一个节点删除移动到另外一颗树上,那么无疑他的儿子的处理会很麻烦,所以我们干脆不删除这个点。而是将这个点的影响变为0,之后用一个新的点去代替这个点,插入到另外一棵树上
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define MAXD 200000 + 100
int n,m;
int fa[MAXD];
int Number[MAXD];
int Sum[MAXD];
int id [MAXD]; /*id[i]表示i当前对应的虚点*/
int find_father(int u){
return u == fa[u] ? u : fa[u] = find_father(fa[u]);
}
int main(){
while(scanf("%d%d",&n,&m) != EOF){
for(int i = 1 ; i < MAXD ;i++){
fa[i] = i;
Number[i] = 1;
Sum[i] = i;
}
for(int i = 1; i <= n; i++)
id[i] = i;
while(m--){
int ord;
scanf("%d",&ord);
if(ord == 1){
int x , y;
scanf("%d%d",&x,&y);
int fx = find_father(id[x]);
int fy = find_father(id[y]);
if(fx != fy){
fa[fx] = fy;
Number[fy] += Number[fx];
Sum[fy] += Sum[fx];
}
}
else if(ord == 2){
int x , y;
scanf("%d%d",&x,&y);
int fx = find_father(id[x]);
int fy = find_father(id[y]);
if(fx != fy){
Number[fx]--;
Sum[fx] -= x;
id[x] = ++n; /*新开一个节点*/
fa[id[x]] = fy;
Number[fy]++;
Sum[fy] += x;
}
}
else if(ord == 3){
int x;
scanf("%d",&x);
int a = find_father(id[x]);
printf("%d %d\n",Number[a],Sum[a]);
}
}
}
return 0;
}