260. [NOI2002] 銀河英雄傳說
公元五八○一年,地球居民遷移至金牛座α第二行星,在那裏發表銀河聯邦創立宣言,同年改元爲宇宙曆元年,並開始向銀河系深處拓展。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=30000+10;
int p[maxn],sum[maxn],cnt[maxn];//sum:distance to root; cnt:count of queue
int find(int x){
if(p[x]==x)return x;
int px=find(p[x]);//真惡毒,要先尋根,不然WA(原因是路徑壓縮前後到祖先的距離不一樣)
sum[x]+=sum[p[x]];//維護到根的長度前綴和:子節點到根節點的距離+=它祖先到根節點的距離
return p[x]=px;
}
void Union(int x,int y){//並集和維護
int px=find(x),py=find(y);
if(px==py)return;
else p[px]=py;
sum[px]+=cnt[py];//到根節點的距離+=隊列戰艦數目
cnt[py]+=cnt[px];//隊列合併,數目增加
}
int Ask(int x,int y){
int px=find(x),py=find(y);
if(px!=py)return -1;//不在一列
else return abs(sum[x]-sum[y])-1;//距離
}
int main()
{
#ifndef DEBUG
string FileName="galaxy";
freopen((FileName+".in").c_str(),"r",stdin);
freopen((FileName+".out").c_str(),"w",stdout);
#endif
int T;
scanf("%d",&T);
for(int i=1;i<=30000;i++)p[i]=i,cnt[i]=1;//每列戰艦的數目初始爲1,根節點是它自己
while(T--){
int x,y;
char s[20];
scanf("%s%d%d",s,&x,&y);
if(s[0]=='M')Union(x,y);
else printf("%d\n",Ask(x,y));
}
}