並查集的實戰使用(綿羊趣題)
上一篇文章,我抄了講了並查集的基本使用,這一次,我搞定了南外的一道綿羊趣題,當中用到了並查集。
話不多說,上題目和程式碼!
並查集趣題
抓羊
(存檔檔名為csheep.pas/c/cpp)
時間限制:1 sec 記憶體限制:128 MB
題目描述
老江帶著hh和南瓜搞不好到內蒙古旅遊,在野外老江想晚上吃燒全羊,於是他命令hh和南瓜搞不好去抓羊。他們倆來到一個地方見到茫茫多的野羊,他們給野羊標號為1..N。他們決定用若干條繩子將野羊相互連線起來帶給老江。當然,任意兩頭野羊之間只有一根繩子直接連線。輸入顯示野羊c1 和野羊 c2是已經連著的。
hh與南瓜搞不好將野羊們相互連在一起而且其中要有1號野羊(野羊首領,不然羊們帶不走)。但南瓜搞不好用繩子綁羊時“見羊就綁”,不論是不是與1號野羊在一起!綁完後,hh急了,想找出不符合要求的野羊,於是用程式找出(升序)沒有直接或間接連到1號羊的野羊編號(當然,1號野羊顯然與自己相連)。假如所有野羊都符合要求,則輸出0。
下面的例子中,有6頭野羊,4根繩子:
1---2 4---5
\ |
\ | 6
\|
3
顯然,4號野羊、5號野羊、6號野羊沒有直接或間接與1號羊相連。
請你也用程式找出不符合要求的野羊。
輸入格式
第1行:兩個用空格隔開的整數: N 與M (1≤N≤300,000,1≤ M≤600,000)其中N代表野羊的只數,M代表綁羊的繩子數。
第2..M+1行:第i+1行有兩個用空格隔開的整數c1和c2,表示野羊c1和野羊c2有繩直接相連 (1≤c1 ≤N; 1≤c2≤ N; c1≠c2)
輸出格式
輸出不符合要求的野羊的序號(升序)。
樣例
csheep.in 6 4 1 3 2 3 1 2 4 5 |
csheep.out 4 5 6 |
資料規模
對於全部的資料,有50%測試資料N≤10,000;
對於全部的資料,有100%測試資料N≤300,000.
原創程式碼
1 #include<bits/stdc++.h> 2 using namespace std; 3 int i,k,n,m,f[300000],p1,p2; 4 int find(int k)//定義find函式 5 { 6 if(f[k]==k)return k; 7 return f[k]=find(f[k]); 8 } 9 intmain() 10 { 11 freopen("csheep.in","r",stdin);//輸入檔案操作,不需要可以註釋掉 12 freopen("csheep.out","w",stdout);//輸出檔案操作 ,不需要可以註釋掉 13 cin>>n>>m; //輸入綿羊的數量,繩子的數量 14 for(i=1;i<=n;i++) 15 { 16 f[i]=i;//初始化,每隻羊都自己綁著自己 17 } 18 for(i=1;i<=m;i++) 19 { 20 cin>>p1>>p2;//重複輸入,互相綁住的羊A和羊B 21 f[find(p1)]=find(p2);//記錄:羊A綁住了羊B 22 } 23 for(i=1;i<=n;i++) 24 { 25 if(find(1)!=find(i))//反覆判斷,如果該羊最終沒有和羊1綁住 26 { 27 cout<<i<<endl;//就輸出它的編號 28 } 29 } 30 return 0; 31 }
這就是並查集趣題之抓羊,喜歡請支援。