合作网络

有n个结点(编号为1..n),初始时每个结点的父亲都不存在。你的任务是执行一次I操作和E操作,格式如下: 
  I u v:把节点u的父亲点设置为v,距离为|u-v|除以1000的余数。输入保证执行指令前u没有父亲节点。 
  E u:询问u 到根接点的距离(输出距离 mod 1000的结果)。


【输入格式】  
  输入第一行为测试数据组数T。每组数据第一行为n(5<=n<=20 000)。接下来有不超过20000行,每一行一条指令,以"O"结尾。I指令的个数不小于n。
  【输出格式】  
  对于每条E指令,输出查询结果。

 

 

 

并查集的路径压缩时维护点到根的距离

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=20010;
inline int read(){
    int x=0,k=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') k=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return k*x;
}
int f[maxn],d[maxn];
int find(int x){
    if(f[x]!=x){
        int root=find(f[x]);
        d[x]+=d[f[x]];
        return f[x]=root;
    }
    else return x;
}
int main(){
    int t,n,u,v;
    t=read();
    while(t--){
        n=read();
        for(int i=1;i<=n;i++) f[i]=i,d[i]=0;
        char c[5];
        while(cin>>c&&c[0]!='O'){
            if(c[0]=='I'){
                u=read();v=read();
                f[u]=v;
                d[u]=abs(u-v)%1000;
            }
            else{
                u=read();
                find(u);
                cout<<d[u]<<endl;
            }
        }
    }
    return 0;
}
View Code

 

posted @ 2018-06-06 15:40  滑稽的大白兔  阅读(193)  评论(1编辑  收藏  举报