並查集模版——實現了路徑壓

來源:互聯網
上載者:User

今天花了時間在網上學了並查集。先上例題,解析在注釋裡。

題目: 親戚(Relations)

或許你並不知道,你的某個朋友是你的親戚。他可能是你的曾祖父的外公的女婿的外甥的表姐的孫子。如果能得到完整的家譜,判斷兩個人是否親戚應該是可行的,但如果兩個人的最近公用祖先與他們相隔好幾代,使得家譜十分龐大,那麼檢驗親戚關係實非人力所能及.在這種情況下,最好的幫手就是電腦。</

為了將問題簡化,你將得到一些親戚關係的資訊,如同Marry和Tom是親戚,Tom和B en是親戚,等等。從這些資訊中,你可以推出Marry和Ben是親戚。請寫一個程式,對於我們的關心的親戚關係的提問,以最快的速度給出答案。

參考輸入輸出格式 輸入由兩部分組成。

第一部分以N,M開始。N為問題涉及的人的個數(1 ≤ N ≤ 20000)。這些人的編號為1,2,3,…,N。下面有M行(1 ≤ M ≤ 1000000),每行有兩個數ai, bi,表示已知ai和bi是親戚.

第二部分以Q開始。以下Q行有Q個詢問(1 ≤ Q ≤ 1 000 000),每行為ci, di,表示詢問ci和di是否為親戚。

對於每個詢問ci, di,若ci和di為親戚,則輸出Yes,否則輸出No。

範例輸入與輸出

輸入relation.in

10 7

2 4

5 7

1 3

8 9

1 2

5 6

2 3

3

3 4

7 10

8 9

輸出relation.out

Yes

No

Yes

#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define maxn 100int father[maxn],rank[maxn];//father表示該節點的父親的序號,rank表示該節點的“輩分”。例如:在1->2->3->4中,4的輩分為3.int n;void makeset(){int i;for(i=1;i<=n;i++){father[i]=i;//由於沒有父親,所以標記父親是自己,有的也可標記為-1.rank[i]=0;//無兒女,所以輩分為0.}}int getfather(int v)//求出該節點的祖父,也就最上面的那個節點。{    if (father[v]==v)      return v;    else    {        father[v]=getfather(father[v]);/*實現了路徑壓縮:舉個例子:如果本來的節點之間關係是1->2->3->4,那麼1,2,3,4的祖父都是4.但是在這個遞迴回溯的時候,father[v]=getfather(father[v]);讓1,2,3,4的father都指向了4,變成了1->4,2->4,3->4,4->4.當尋找1的祖父時,只要尋找一次就能找到,而不是原來的3次, 這樣的結構讓尋找起來更加的快速,路徑壓縮的快捷也就體現出來。*/        return father[v];     }}void Union(int x,int y)//如果x,y不屬於一個集合,讓他們合并成一個集合,操作是讓x的祖父變成y的祖父。{ //注意這裡是預設讓x的祖父變成y的祖父,如果y的祖父的rank比x的祖父的rank大,那麼則讓y的祖父變成x的祖父。//void judge(int x ,int y) 將考慮這種情況。int fx,fy;    fx=getfather(x);    fy=getfather(y);    if(fy!=fx)       father[fx]=fy;}bool same(int x,int y)//判斷是否是同一個集合{   return getfather(x)==getfather(y);}void judge(int x ,int y) //在void Union(int x,int y)預設讓x的祖父變成y的祖父,這裡考慮如果y的rank比x的rank大,那麼則讓y的父親變成x。這樣做為了路徑壓縮。{//if (rank[fx]>rank[fy]) 則y的輩分+1.int fx,fy;     fx = getfather(x);     fy = getfather(y);     if (rank[fx]>rank[fy])        father[fy] = fx;     else     {        father[fx] = fy;        if(rank[fx]==rank[fy])           ++rank[fy];     }}int main(){int m,i;int a,b;while(cin>>n>>m){makeset();for(i=1;i<=m;i++){cin>>a>>b;if(!same(a,b))//判斷是否為一個集合{Union(a,b);judge(a,b);//實現路徑壓縮 }}cin>>m;for(i=1;i<=m;i++){cin>>a>>b;if(same(a,b))cout<<"Yes"<<endl;elsecout<<"No"<<endl;}}return 0;} 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.