版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40924940/article/details/84953428
题意如下
n 个城市每个城市有一个编号与城市同名为 i 的龙珠
有Q 个事件
T A B 代表A城市里所有龙珠移动到了B城市
Q A 代表询问 A,输出 A 龙珠所在城市,所在城市一共多少个龙珠,A一共移动了几次。。。
简单并查集,每次询问一个龙珠时,父节点全部的移动加上自己的移动就是A一共移动的次数,之后合并的时候只需把 pre[a] 设为 b 同时 a 移动次数 +1, b城市龙珠数目 加上 a城市龙珠数目,a城市龙珠数目清零即可。。。
以下是 AC 代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 1e5+5;
int pre[maxn],ans[maxn],num[maxn];
int t,n,m;
int findd(int x)
{
int t;
if(pre[x]==x) return x;
else
{
t=findd(pre[x]);
ans[x]+=ans[pre[x]];
pre[x]=t;
return pre[x];
}
}
void unite(int a,int b)
{
int x=findd(a);
int y=findd(b);
if(x!=y)
{
pre[x]=y;
ans[x]++;
num[y]+=num[x];
num[x]=0;
}
}
int main()
{
int x,y;
int sum=0;
int n,q;
char a[2];
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
pre[i]=i;
num[i]=1;
ans[i]=0;
}
printf("Case %d:\n",++sum);
for(int i=1;i<=q;i++)
{
scanf("%s",a);
if(a[0]=='T')
{
scanf("%d%d",&x,&y);
unite(x,y);
}
else
{
scanf("%d",&x);
int fx = findd(x);
printf("%d %d %d\n",fx,num[pre[x]],ans[x]);
}
}
}
return 0;
}