
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个龙珠和n个城市,第i颗龙珠在第i座城市。下面有两种操作:
T A B 将A龙珠所在的城市的所有龙珠移动到第B个龙珠所在的城市
Q A 询问A龙珠所在的城市,这座城市有多少颗龙珠,A龙珠被移动了多少次
思路:询问的前两个问题都很好解决,有难度的是第三个问题,龙珠被移动的次数。这个次数的问题,本来如果不适用压缩路径的话,次数就是节点到根节点的路径长度(这个我早上才想明白,嚓),那么现在使用了压缩路径了,就要在压缩的时候顺便把路径长度也存下来.
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<string>
#include<stdio.h>
using namespace std;
int pre[10010];
int trans[10010];
int ranks[10010];
int union_find(int node)
{
int temp;
if(node==pre[node])return node;
else
{
temp=pre[node];
pre[node]=union_find(pre[node]);
trans[node]+=trans[temp];
}
return pre[node];
}
int main(int argc, char *argv[])
{
// freopen("3635.in","r",stdin);
int T,N,Q,a,b;
scanf("%d",&T);
char s[10];
int total=T;
while(T--)
{
scanf("%d %d",&N,&Q);
printf("Case %d:\n",total-T);
memset(pre, 0, sizeof(pre));
memset(trans, 0, sizeof(trans));
memset(ranks, 0, sizeof(ranks));
for(int i=1;i<=N;++i){
pre[i]=i;
ranks[i]=1;
}
while(Q--)
{
scanf("%s",s);
if(s[0]=='T')
{
scanf("%d %d",&a,&b);
int p=union_find(a);
int q=union_find(b);
if(p!=q){
ranks[q]+=ranks[p];//b的节点数增加a的节点数
pre[p]=q;//a的根嫁接到b的根上
trans[p]++;
ranks[p]=0;
}
}
else
{
scanf("%d",&a);
union_find(a);
printf("%d %d %d\n",pre[a],ranks[pre[a]],trans[a]);
}
}
}
return 0;
}
原文:http://blog.csdn.net/wdkirchhoff/article/details/41752539