题意:
初始时,有n个龙珠,编号从1到n,分别对应的放在编号从1到n的城市中。
现在又2种操作:
T A B,表示把A球所在城市全部的龙珠全部转移到B城市。(第一次时,因为A球所在的城市只有一个球,所以只移动1个,如果有多个,则全部移动)。
Q A,表示查询A。要求得到的信息分别是:A现在所在的城市,A所在城市的龙珠数目,A转移到该城市移动的次数(如果没有移动就输出0)
题解:
并查集,需要用到路径压缩,每次移动根结点的移动次数+1,,计算路径是,求子节点的路径加上根结点移动次数即可。
#include <iostream>
using namespace std;
const int maxn = 10005;
struct Node{
int fa;
int son;
int tran;
}p[maxn];
int find(int x){
if(x==p[x].fa)
return x;
int temp = p[x].fa;
p[x].fa = find(p[x].fa);
p[x].tran += p[temp].tran;
return p[x].fa;
}
void join(int x,int y){
int tx,ty;
tx = find(x);
ty = find(y);
if(tx==ty) return;
p[tx].fa = ty;
p[tx].tran++;
p[ty].son += p[tx].son;
p[tx].son = 0;
}
int main(){
int t,n,m,a,b;
int kase = 0;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
p[i].fa = i;
p[i].son = 1;
p[i].tran = 0;
}
printf("Case %d:\n",++kase);
char s[5];
while(m--){
scanf("%s",s);
if(s[0]=='T'){
scanf("%d%d",&a,&b);
join(a, b);
}else{
scanf("%d",&a);
int ans = find(a);
printf("%d %d %d\n",ans,p[ans].son,p[a].tran);
}
}
}
return 0;
}