题解
带权并查集,准备三个数组:
fa[x]
表示x节点的祖先
sz[x]
表示x集合的大小
d[x]
表示集合内部的节点到祖先结点的距离
内部 - find(x)
:更新fa[x]的同时,更新集合内部的节点到祖先结点的距离
外部 - 见代码
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,k;
int fa[N],sz[N],d[N];//sz[i]表示第i列飞船的总数 d[i]表示第i个飞船到队头的距离
int find(int x){
if(fa[x]==x)return x;
int fx=find(fa[x]);
d[x]+=d[fa[x]];//(队列内部)更新到头的距离
return fa[x]=fx;
}
char op;
int x,y;
int main(){
for (int i = 1; i <= N; ++i) {//init
fa[i]=i;
sz[i]=1;
d[i]=0;
}
int T;
scanf("%d",&T);
for (int cs = 1; cs <= T; ++cs) {
scanf(" %c%d%d",&op,&x,&y);
if(op=='M'){//合并 y是新的祖先 题目要求
x=find(x);
y=find(y);
fa[x]=y;//y是新的队列的头
d[x]+=sz[y];//更新队头x的距离(内部在find函数里面更新)
sz[y]+=sz[x];//更新队列y的总数
sz[x]=0;//队列x清零
}else{
if(find(x)!=find(y))puts("-1");
else printf("%d\n", abs(d[x]-d[y])-1);
}
}
return 0;
}