题目
他的国家有N个城市,世界上正好有N个龙珠。首先,对于第i个龙珠,神龙将把它放在第i个城市。经过漫长的岁月,一些城市的龙珠会被运送到其他城市。为了救体力,悟空计划带着飞天雨云,一种神奇的飞天云来收集龙珠。
每次悟空收集一个龙珠的信息,他都会问你那个龙珠的信息。你必须告诉他球在哪个城市,那个城市有多少个龙珠,你还需要告诉他球到目前为止已经运了多少次。
输入
输入的第一行是一个正整数T(0 < T <= 100)。
对于每种情况,第一行包含两个整数:N和Q (2 < N <= 10000, 2 < Q <= 10000)。
以下每一行都包含一个事实或一个问题,格式如下:
所有和A在同一个城市的龙珠都已经被运到了B球所在的城市。你可以假设这两个城市是不同的。
问:悟空想知道X(城中Ath球的id), Y(城中X球的数量),Z(城中Ath球的转运时间)。(1 <= A, B <= N)
输出
对于每个测试用例,输出被格式化为示例输出的测试用例编号。然后,对于每个查询,输出一行带有三个整数(X Y Z)的行,它们之间用空格隔开。
题解:
需要求一个球的移动次数。这就是带权并查集。合并的时候cnt[ra]++;
#include<bits/stdc++.h>
using namespace std;
const int N=10000+5;
int f[N],cnt[N],sum[N];
int seek(int x){
if(x==f[x]) return x;
int fa=f[x];
f[x]=seek(f[x]),cnt[x]+=cnt[fa];
return f[x];
}
int main(){
int T,cas=0;scanf("%d",&T);
while(T--){
int n,m;scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) f[i]=i,cnt[i]=0,sum[i]=1;
char ch[3];
int a,b,x,flag=0;
while(m--){
scanf("%s",ch);
if(ch[0]=='T'){
scanf("%d%d",&a,&b);int ra=seek(a),rb=seek(b);
if(ra!=rb) f[ra]=rb,++cnt[ra],sum[rb]+=sum[ra];
}
else{
if(!flag) printf("Case %d:\n",++cas);
flag=1;
scanf("%d",&x);int rx=seek(x);
printf("%d %d %d\n",rx,sum[rx],cnt[x]);
}
}
}
}