https://vjudge.net/problem/UVALive-3027
题意:
一开始有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<set>
#include<vector>
#include<string.h>
#include<algorithm>
#include<cmath>
using namespace std;
vector<int> parent;
vector<int> jl;
int main() {
int root(int p);
void uni(int p, int q);
int t,N;
cin>>t;
while(t--) {
cin>>N;
parent.resize(N+1);
jl.resize(N+1);
for(int i=0; i<N+1; i++) {
parent[i]=i;
jl[i]=0;
}
int a,b,res;
char c;
while(true) {
cin>>c;
if(c=='E') {
scanf("%d",&a);
root(a);
cout<<jl[a]<<endl;
} else if(c=='I') {
scanf("%d %d",&a,&b);
uni(a,b);
} else {
break;
}
}
}
return 0;
}
int root(int p) {
if(p != parent[p]) {
int rt=root(parent[p]);
jl[p]+=jl[parent[p]];
return parent[p]=rt;
}
return parent[p];
}
void uni(int p, int q) {
/*int res=0;
int proot = root(p,res);
int qroot = root(q,res);
if(proot == qroot)
cout<<"Error"<<endl ;*/
parent[p] =q;
jl[p]=abs(p-q)%1000;
}