题目链接:点击进入
题意:
一开始有n个点,每个点都没有父节点。接下来不断执行I操作和E操作,直到执行O操作时结束;
I操作:I u v,u的父节点为v,路线长度为|u-v|%1000,保证u不存在起始父节点。
E操作:E u,查询u到其根节点的距离,输出。
题解:
并查集+路径压缩。
由于I操作时保证了u开始没有父节点,所以构成的是树;之后只是求点到跟的距离,所以只要用并查集即可,之后用路径压缩减少计算路径的时间。fa[x]一开始表示的是x的父节点,之后一次并查集查询后fa[x]表示的是x的根节点;在查询过程中d[x]表示x到fa[x]的距离,而在查找的时候还会维护所有路径上的点到根节点的距离,减少了下次查询的时间。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 22000
int fa[maxn],d[maxn];
int abs(int a)
{
if(a<0)a=-a;
return a;
}
int Find(int x)
{ ///注意这里的压缩顺序
if(fa[x]!=x)
{
int rt=Find(fa[x]);
d[x]+=d[fa[x]];
return fa[x]=rt;
}
else
return x;
}
int main()
{
//freopen("in.txt","r",stdin);
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
fa[i]=i;
d[i]=0;
}
char str[10];
while(scanf("%s",str))
{
int a,b;
if(str[0]=='O') break;
if(str[0]=='E')
{
scanf("%d",&a);
Find(a);
printf("%d\n",d[a]);
}
else
{
scanf("%d%d",&a,&b);
fa[a]=b;
d[a]=abs(a-b)%1000;
}
}
}
return 0;
}