[NOI2002] 银河英雄传说
题目链接:###
题目分析:###
带权并查集的题,记一个\(d\)数组维护每个战舰前面有多少战舰,再在每个树根上记录一个集合大小\(sum\),每次进行\(get_father\)的时候维护一下\(d\)数组,合并的时候更新集合大小。由于写了路径压缩,每次合并的时候还要把之前集合的\(sum\)更新到\(d\)数组上。
代码:###
#include<bits/stdc++.h>
#define N (1000000+5)
using namespace std;
inline int read(){
int cnt=0,f=1;char c;
c=getchar();
while(!isdigit(c)){
if(c=='-') f=-f;
c=getchar();
}
while(isdigit(c)){
cnt=cnt*10+c-'0';
c=getchar();
}
return cnt*f;
}
int t,fa[N],d[N],sum[N],x,y;
char c;
int get_father(int x){
if(fa[x]==x)return x;
int root=get_father(fa[x]);
d[x]+=d[fa[x]];
return fa[x]=root;
}
void merge(int x,int y){
int a=get_father(x);
int b=get_father(y);
fa[a]=b;d[a]=sum[b];
sum[b]+=sum[a];
}
int query(int x,int y){
int a=get_father(x);
int b=get_father(y);
if(a!=b) return -1;
else {
int ans=abs(d[x]-d[y])-1;
return ans;
}
}
int main(){
t=read();
for(register int i=1;i<=30001;i++) fa[i]=i,d[i]=0,sum[i]=1;
for(register int i=1;i<=t;i++) {
cin>>c;x=read();y=read();
if(c=='M') merge(x,y);
if(c=='C') printf("%d\n",query(x,y));
}
return 0;
}