洛谷 1196 銀河英雄傳說 並查集

題目描述:

       楊威利擅長排兵佈陣,巧妙運用各種戰術屢次以少勝多,難免恣生驕氣。在這次決戰中,他將巴米利恩星域戰場劃分成30000列,每列依次編號爲1, 2, …,30000。之後,他把自己的戰艦也依次編號爲1, 2, …, 30000,讓第i號戰艦處於第i列(i = 1, 2, …, 30000),形成“一字長蛇陣”,誘敵深入。這是初始陣形。當進犯之敵到達時,楊威利會多次發佈合併指令,將大部分戰艦集中在某幾列上,實施密集攻擊。合併指令爲M i j,含義爲讓第i號戰艦所在的整個戰艦隊列,作爲一個整體(頭在前尾在後)接至第j號戰艦所在的戰艦隊列的尾部。顯然戰艦隊列是由處於同一列的一個或多個戰艦組成的。合併指令的執行結果會使隊列增大。 然而,老謀深算的萊因哈特(這絕對與OW無關)早已在戰略上取得了主動。在交戰中,他可以通過龐大的情報網絡隨時監聽楊威利的艦隊調動指令。在楊威利發佈指令調動艦隊的同時,萊因哈特爲了及時瞭解當前楊威利的戰艦分佈情況,也會發出一些詢問指令:C i j。該指令意思是,詢問電腦,楊威利的第i號戰艦與第j號戰艦當前是否在同一列中,如果在同一列中,那麼它們之間佈置有多少戰艦。作爲一個資深的高級程序設計員,你被要求編寫程序分析楊威利的指令,以及回答萊因哈特的詢問。最終的決戰已經展開,銀河的歷史又翻過了一頁……


輸入格式:

        輸入文件galaxy.in的第一行有一個整數T(1<=T<=500,000),表示總共有T條指令。以下有T行,每行有一條指令。指令有兩種格式:M i j :i和j是兩個整數(1<=i , j<=30000),表示指令涉及的戰艦編號。指令是萊因哈特竊聽到的楊威利發佈的艦隊調動指令,並且保證第i號戰艦與第j號戰艦不在同一列。C i j :i和j是兩個整數(1<=i , j<=30000),表示指令涉及的戰艦編號。指令是萊因哈特發佈的詢問指令。

輸出格式:

       輸出文件爲galaxy.out。你的程序應當依次對輸入的每一條指令進行分析和處理:如果是楊威利發佈的艦隊調動指令,則表示艦隊排列發生了變化,你的程序要注意到這一點,但是不要輸出任何信息;如果是萊因哈特發佈的詢問指令,你的程序要輸出一行,僅包含一個整數,表示在同一列上,第i 號戰艦與第j 號戰艦之間佈置的戰艦數目。如果第i 號戰艦與第j號戰艦當前不在同一列上,則輸出-1。


輸入樣例:

  4

M 2 3

C 1 2

M 2 4

C 4 2

輸出樣例:

-1

1


解題思路:

並查集,設b,c數組,b[i]表示第i艘飛船前有多少艘,c[i]表示第i艘後有幾艘。合併時,如把i接到j後 b[i]=c[j];c[j]=c[j]+c[i]

代碼:

#include<cstring>#include<cstdio>#include<iostream>#include<cmath>using namespace std;int m,i,j,n,tot;int f[300000],c[300000],b[300000];int getfather(int x){ if (f[x]==x) return x; int i; i=getfather(f[x]); b[x]=b[x]+b[f[x]]; return f[x]=i;}void me(int x,int y){ int i,j; i=getfather(x); j=getfather(y); f[i]=j; b[i]=c[j]; c[j]=c[i]+c[j]; }void ask(int x,int y){ int i,j; i=getfather(x); j=getfather(y); if(i==j) { int ans; ans=abs(b[x]-b[y])-1; printf("%d\n",ans); } else printf("-1\n"); }int main(){ char s; scanf("%d\n",&n); for(int i=1;i<=n;i++) { f[i]=i; b[i]=0; c[i]=1; } for(int i=1;i<=n;i++) { int x,y; scanf("%c %d%d\n",&s,&x,&y); if(s=='M') me(x,y); else ask(x,y); } return 0; } 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章