题目链接
题目描述:第i个龙珠在第i个城市,如果是T a b,就是a城市往b城市移动,如果是Q a就是输出a在哪个城市,接着输出该城市持有的龙珠数量,还有a移动时间。
思路:
1)a所在城市即在求a的父节点;还有就是每个城市未移动之前时间都是0、个数都是自己本身一个、每个点的父节点都为自己本身。
2)所以在执行上面操作时需要先找a,b各自的父节点。
在找父节点时,如果x!=p[x]了,说明x之前有移动到p[x]这个城市,那么x的移动时间得加上p[x]的移动时间。
找完后a,b的父节点后(设找到的父节点仍为a,b),这时b就成了a的父节点,那么b持有的龙珠数量得加上a本身的龙珠数,同时也要记录a的移动时间。
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int p[200005],time[200005],sum[200005],X;
int Find(int x)
{
if(x!=p[x])
{
int l=p[x];
p[x]=Find(p[x]);
time[x]+=time[l];//由于x!=p[x]了,也就是x曾经移动到p[x]那,x的移动时间得加上p[x]的时间
return p[x];
}
return x;
}
void Union(int x,int y)
{
x=Find(x);
y=Find(y);
if(x!=y)
{
p[x]=y;
sum[y]+=sum[x];//x移到y,那么y得加上x的那一份
time[x]++;
//x移动了得记录
}else return;//如果相等要返回
}
int main()
{
int t,n,k,a,b;
char s[5];
scanf("%d",&t);
for(int j=1; j<=t; j++)
{
scanf("%d%d",&n,&k);
for(int i=1; i<=n; i++)//**这应该从1开始 **
{
p[i]=i;
sum[i]=1;
time[i]=0;
}
printf("Case %d:\n",j);
for(int i=0; i<k; i++)
{
scanf("%s",&s);
if(s[0]=='T')
{
scanf("%d%d",&a,&b);
Union(a,b);
}
else
{
scanf("%d",&a);
X=Find(a);//**找a的父节点**
printf("%d %d %d\n",X,sum[X],time[a]);
}
}
}
return 0;
}