标签:并查集
2 3 3 T 1 2 T 3 2 Q 2 3 4 T 1 2 Q 1 T 1 3 Q 1
Case 1: 2 3 0 Case 2: 2 2 1 3 3 2
这题考查了并查集的路径压缩,这道题让我对路径压缩有了进一步了解,题意是初始时,有n个龙珠,编号从1到n,分别对应的放在编号从1到n的城市中。2种操作:
T A B,表示把A球所在城市全部的龙珠全部转移到B城市。 Q A,表示查询A。要求得到的信息分别是:A现在所在的城市,A所在城市的龙珠数目,A转移到该城市移动的次数(如果没有移动就输出0)这里难点是求出询问的这个球转移的次数,这里设一个函数zhuanyi[n],初始化为0,每次移动的时候,这个球的祖先转移次数为1(其实以每个城市为祖先的移动最多只有一次,其他都是跟着自己的祖先移动),然后用并查集递归压缩路径的方法,使得当前这个点加上自己所有祖先的转移次数,然后使自己的祖先变为当前转移的城市,这样就能保证下次不会重复加。#include<stdio.h> #include<string.h> int pre[10006],zhuanyi[10006],num[10006]; char s[10]; int find(int x) { int temp; if(x==pre[x])return x; temp=pre[x]; pre[x]=find(pre[x]); zhuanyi[x]+=zhuanyi[temp]; return pre[x]; } int main() { int T,n,m,i,j,a,b,c,t1,t2,num1=0; scanf("%d",&T); while(T--) { num1++; printf("Case %d:\n",num1); scanf("%d%d",&n,&m); for(i=1;i<=n;i++){ pre[i]=i;zhuanyi[i]=0;num[i]=1; //pre[]表示球的父亲,zhuangyi[]表示球转移的次数,num[i]表示球i所在城市的球的个数 } for(i=1;i<=m;i++){ scanf("%s",s); if(s[0]==‘T‘){ scanf("%d%d",&a,&b); t1=find(a);t2=find(b); if(t1==t2)continue; pre[t1]=t2; num[t2]+=num[t1]; zhuanyi[t1]=1; } else if(s[0]==‘Q‘){ scanf("%d",&a); t1=find(a); printf("%d %d %d\n",t1,num[t1],zhuanyi[a]); } } } return 0; }
标签:并查集
原文地址:http://blog.csdn.net/kirito_acmer/article/details/45642987