题目描述
维护并查集的次序
考虑如何在合并的时候维护深度。
其实你想一下d[x]的定义就是x到root的距离。那么在什么时候会改变?
1、执行M操作,整体移动,那么a队列的所有战舰都被转移到b的后面。a的d要变
2、对于不是头结点的战舰,在找root的时候要考虑:是否自己原来的root现在d[fa[x]]已经不是0了,不是0就意味着他不是头节点了,那么你就一定要改变了。
//在find函数里的变动
if(fa[x]!=x)
{
int root=find(fa[x]);
d[x]+=d[fa[x]]; //关键的一步
fa[x]=root;
}
//在Merge的时候
fa[pa]=pb;
d[pa]=sz[pb];
sz[pb]+=sz[pa];
#include<bits/stdc++.h>
using namespace std;
int sz[30010],d[30010],fa[30010];
int find(int x)
{
if(fa[x]!=x)
{
int root=find(fa[x]);
d[x]+=d[fa[x]];
fa[x]=root;
}
return fa[x];
}
int main()
{
int t;
for(int i=0;i<30010;i++) d[i]=0,sz[i]=1,fa[i]=i;
cin>>t;
while(t--){
char op[2];
int a,b;
scanf("%s%d%d",op,&a,&b);
int pa=find(a),pb=find(b);
if(op[0]=='M'){
if(pa!=pb)
{
fa[pa]=pb;
d[pa]=sz[pb];
sz[pb]+=sz[pa];
}
}
else{
if(pa!=pb) cout<<-1<<endl;
else printf("%d\n",max(0,abs(d[a]-d[b])-1));
}
}
return 0;
}
代码太棒了!
存的不是x到父节点的距离么?不是根节点吧
确实,严格讲应是x到其父节点距离,但因为find()函数进行了路径压缩,当查询某个节点 i 时,如果 i 的父节点不为根节点的话,就会进行递归调用,将 i 节点沿途路径上所有节点均指向父节点,此时的 d[i] 存放的是 i 到父节点,也就是根节点的距离。
请问一下代码里面sz数组是做什么的呢
你好,sz数组是用来维护size大小的,就是x所在连通块所有点的数量。
好文,简洁明了