LA 3027 Corporative Network 并查集记录点到根的距离 (二)

2014-11-24 00:33:25 · 作者: · 浏览: 10
find(I);
cout< break;
}
}
}
}
return 0;
}

#include
using namespace std;
const int maxn = 20000 + 10;
int d[maxn], fa[maxn];
int find(int x)
{
if(x == fa[x]) return x;
else
{
int root = find(fa[x]);
d[x] += d[fa[x]];
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':
{
//int x,y;
cin>>I>>J;
/* x=find(I);
y=find(J);
if(x==y) continue;
fa[x]=y;
*/
fa[I] = J;
int ans = I > J (I-J) : (J-I);
d[I] =ans % 1000;
break;
}
case 'E':
{
cin>>I;
find(I);
cout< break;
}
}
}
}
return 0;
}

不能按代码中注释的 那样

x=find(I);

y=find(J);

if(x==y) continue;

fa[x]=y;

代替 fa[I] = J;

一换掉 就wa

: 假设用dis表示点到根的距离

因为 为了求dis 所以谁的父亲就是谁的父亲 不能压缩 , 但是上面的find代码是进行压缩的 不过它是在递归求dis后 才压缩的 所以说 是可以压缩的

即 必须先递归 后压缩 这样就能保证求出的dis 确实是按照父亲节点算出来的

上面的那个错误 是由于先调用find函数压缩 ,这时候 点 I 的 dis还没有算出来,后面再求它的dis的时候 其就不再是按照真正的父亲节点找出的 而是按照祖先节点算的(因为压缩过了)

对于之后输入E 再次调用fand函数的时候 虽然已经压缩过了 但是所有点的dis已经求出来了 对于再加入的边 I J 我们依旧能够通过接到已经求出的正确dis 求出来I 的dis

注意dis表示 点到根的距离