题目大意:初始时,有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 <stdio.h> #include <string.h> #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; }