$\huge \color{orange}{成魔之路->}$ $\huge \color{purple}{算法提高课题解}$
思路:
1. 并查集的本质是一棵树,让父节点直接指向根节点
2. s 维护该集合大小,合并时只要让 d[pa] = s[pb] 即可
3. d 维护该节点到根节点的距离 = 该点到父节点的距离 + 父节点到根节点的距离
4. 只有 find 的时候才会更新该点到根节点的距离
完整代码
#include<bits/stdc++.h>
using namespace std;
const int N = 30010;
int n;
int p[N],s[N],d[N];
//使得路径上的点直接指向根节点
int find(int x)
{
if(p[x]!=x)
{
int root=find(p[x]);
//该点到根节点的距离 = 该点到父节点的距离 + 父节点到根节点的距离
d[x]+=d[p[x]];
//使该点的父节点直接指向根节点
p[x]=root;
}
return p[x];
}
int main()
{
cin>>n;
//初始化
for(int i=1;i<N;i++)
{
p[i]=i;
s[i]=1;
}
while(n--)
{
char op;
int a,b;
cin>>op>>a>>b;
//必须 find 一遍才会更新距离
int pa=find(a),pb=find(b);
if(op=='M')
{
if(pa!=pb)
{
// a 根节点到 b 根节点的距离为 b 的集合大小
d[pa]=s[pb];
//更新集合元素个数
s[pb]+=s[pa];
//合并集合
p[pa]=pb;
}
}
else
{
if(pa!=pb) cout<<-1<<endl;
else cout<<max(abs(d[a]-d[b])-1,0)<<endl;
}
}
return 0;
}