对I操作,直接连上该点与父节点即可
对E操作,用findlen函数,会找到a的根节点,并且在找的过程中更新a到根节点之间所有点到根节点的距离,从而下次查找复杂度为O(1) (如果查找的点为a到根节点之间的点,included)
1#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
int f[20000+5];
int dis[20000+5];
int findlen(int tmp)
{
if (tmp==f[tmp])
return tmp;
int root=findlen(f[tmp]);
dis[tmp]=dis[tmp]+dis[f[tmp]]; //用递归是为了给从最后到前面的每个点计算到根的距离
f[tmp]=root;
return root;
}
int main()
{
int i,j,t,n,a,b;
int m;
scanf("%d",&t);
for (i=1;i<=t;i++)
{
scanf("%d",&n);
for(j=1;j<=n;j++)
{
f[j]=j;
dis[j]=0;
}
getchar();
while(1)
{
char c;
scanf("%c",&c);
if (c=='O') break;
if (c=='I')
{
scanf("%d%d",&a,&b);
getchar();
f[a]=b;
dis[a]=(abs(a-b) )%1000; //记录自己与直接点的距离
}
if (c=='E')
{
scanf("%d",&a);
getchar();
int len =0;
findlen(a);
printf("%d\n",dis[a]);
}
}
}
return 0;
}