题目大意:初始时,有n个龙珠,编号从1到n,分别对应的放在编号从1到n的城市中。现在有两种操作:
T A B,表示把A球所在城市全部的龙珠全部转移到B城市。(第一次时,因为A球所在的城市只有一个球,所以只移动1个,如果有多个,则全部移动)。
Q A,表示查询A。要求得到的信息分别是:A现在所在的城市,A所在城市的龙珠数目,A转移到该城市移动的次数(如果没有移动就输出0)
这道题主要的问题是转移次数,初始时每个龙珠的转移次数为0,若将a移到b,则将a所在集合的根结点加一,表示整个a集合都移动了一次,如果查找某个节点x的移动次数,则在路径压缩时需要加上它父节点的移动次数,递归解决。
#include
#include
#define maxn 10200
int p[maxn],tran[maxn],cap[maxn];
int t;
int find(int x)
{
int a;
if(p[x]==x) return x;
else
{
a=find(p[x]);
tran[x]+=tran[p[x]];
p[x]=a;
return p[x];
}
}
void link(int a,int b)
{
int x,y;
x=find(a);
y=find(b);
if(x!=y)
{
p[x]=y;
tran[x]++;
cap[y]+=cap[x];
cap[x]=0;
}
}
int main()
{
int i,x,y;
int sum=0;
int n,q;
char a;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&q);
for(i=1;i<=n;i++) { p[i]=i;cap[i]=1;tran[i]=0; }
sum++;
printf("Case %d:\n",sum);
for(i=1;i<=q;i++)
{
getchar();
scanf("%c",&a);
if(a=='T')
{
scanf("%d%d",&x,&y);
link(x,y);
}
else
{
scanf("%d",&x);
int ans=find(x);
printf("%d %d %d\n",ans,cap[p[x]],tran[x]);
}
}
}
return 0;
}