题目大意:有N个结点,初始时每个结点的父亲都不存在,你的任务时执行一次I操作和E操作,格式如下:
I u v :把结点u的父节点设为v,距离为|u-v|除以1000的余数,输入保证执行指令前u 没有父节点
E u :询问u 到根节点的距离
解题报告:带距离的并查集,在每次合并父亲节点的时候更新一个距离就可以了
并查集参考刘汝佳的findset函数
‘
#include<iostream>
#include<cstdio>
#define maxn 20120
using namespace std;
struct node
{
int dis;
int fa;
}p[maxn];
int oabs(int x)
{
return x<0?-x:x;
}
int findset(int x)
{
if(p[x].fa==x)return x;
else
{
int tf=p[x].fa;//先把该节点的临时父亲记录下来
int f=findset(p[x].fa);
p[x].fa=f;
p[x].dis+=p[tf].dis; //用临时父亲的距离去更新此节点
return f;
}
}
int main()
{
int n,T;
int u,v;
char type;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=0;i<=n;i++)
{
p[i].fa=i;
p[i].dis=0;
}
while(cin>>type&&type!='O')
{
if(type=='I')
{
scanf("%d%d",&u,&v);
p[u].fa=v;
p[u].dis=oabs(u-v)%1000;
}
else
{
scanf("%d",&u);
findset(u);
printf("%d\n",p[u].dis);
}
}
}
return 0;
}