LA - 3027 - Corporative Network
题意:有N个企业,企业间要进行合作,于是需要连线,I I J表示将I连到J去,即J作为I的父结点,有一系列的询问,E I 表示询问I到根结点的连线距离是多长,输出这个结果。
——>>用并查集连起来即可。主要在于,用d[i]表示从i到根结点的距离,但在初始化后第一次赋值时应为i到其父结点的距离,如果不是的话,可能会出现修改一个结点,则其所有子结点都要修改的繁琐现象。若有1-2-3-4,担心会出现查4时d[4] = d[4] + d[3]而d[3]没改为3到根的距离?不用担心,find是递归,深度优先,在执行d[4] = d[4] + d[3]前已执行为d[3] = d[2] + d[1],更先执行为d[2] = d[2] + d[1]。
#include <iostream> using namespace std; const int maxn = 20000 + 10; //企业数5 <= N <= 20000 int d[maxn], fa[maxn]; //d[i]点i到根结点的距离(但初始化后第一次给的值是i到其父结点的距离),fa[i]为结点i的父结点 int find(int x) //带路径压缩的查找函数 { if(x == fa[x]) return x; else { int root = find(fa[x]); d[x] += d[fa[x]]; //改为到根的距离,这里不需考虑是否要对1000取模 return fa[x] = root; //路径压缩 } } int main() { int T, N, i, I, J; cin>>T; while(T--) { cin>>N; for(i = 0; i <= N; i++) //初始化 { fa[i] = i; //根树 d[i] = 0; //自己到自己(根)的距离为0 } char c; bool ok = 1; //是否退出的标记 while(ok && cin>>c) { switch(c) { case 'O': { ok = 0; break; } case 'I': { cin>>I>>J; fa[I] = J; int ans = I > J ? (I-J) : (J-I); d[I] = ans % 1000; //赋该点到其父结点的距离值 break; } case 'E': { cin>>I; find(I); //find会维护(将d[I]改为该点到根的距离)该点到根的距离 cout<<d[I]<<endl; break; } } } } return 0; }