题意:有两种操作。1,将u设为v的父亲结点,距离为abs(u-v)%1000;2,求u到根节点的距离。
思路:带权并查集。设dist[u]表示u到根节点的距离,每次压缩路径时,需要每次加上其父亲结点的dist。另外在合并时计算为dist[v]=abs(u-v)%1000+dist[u]。
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int mod=1000;
const int maxn=20005;
int father[maxn];
int dist[maxn];
void init(int n)
{
for(int i=1; i<=n; ++i)
father[i]=i,dist[i]=0;
}
int find(int p)
{
if(p==father[p])
return p;
else
{
int q=father[p];
father[p]=find(father[p]);
dist[p]+=dist[q];
return father[p];
}
}
//将a的父亲设为b的祖先
void unio(int a,int b)
{
father[a]=b;
dist[a]=abs(a-b)%mod;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
init(n);
char p[3];
int a,b;
while(scanf("%s",p)&&p[0]!='O')
{
if(p[0]=='E')
{
scanf("%d",&a);
find(a);
printf("%d\n",dist[a]);
}
else
{
scanf("%d%d",&a,&b);
unio(a,b);
}
}
}
return 0;
}