银河英雄传说【并查集】

​NOI2002​​​、​​CH4101​​​、​​ACwing238​

#include<bits/stdc++.h>
using namespace std;

#define
const int N = 300000;

int father[N + 5],dis[N + 5],siz[N + 5]; //分别记录祖先、距离、集合大小

int find_f(int x){ //找到祖先结点并且更新dis和father数组
if(father[x] == x)
return x;
int root = find_f(father[x]); //先遍历
dis[x] += dis[father[x]]; //等到遍历结束,父亲结点更新之后再更新该结点
return father[x] = root; //路径压缩
}

void solve(){
for(int i = 1;i <= N;++i){ //初始化
father[i] = i;siz[i] = 1;
}
int T,x,y,fx,fy;
char ch;
cin>>T;
while(T--){
cin>>ch>>x>>y;
fx = find_f(x),fy = find_f(y);
if(ch == 'M'){ //合并
dis[fx] = siz[fy]; //结点x所在集合的祖宗结点应该放在结点y所在集合之后,
//所以结点x的祖先的距离应该刚好是结点y所在集合的大小
siz[fy] += siz[fx]; //结点x所在集合连接在集合y所在集合之后的话,集合y所在集合的大小会变大累加
father[fx] = fy; //合并
}
else{
if(fx != fy)
cout<<"-1\n";
else{
//注意C x x这种格式距离应该是0
x = 0 > abs(dis[x] - dis[y]) - 1 ? 0 : abs(dis[x] - dis[y]) - 1;
cout<<x<<"\n";
}
}
}
}

signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
// int tt;
// cin>>tt;
// while(tt--)
solve();
return 0;
}