並查集專欄

並查集 程序=數據結構+算法。
並查集是一種數據結構:針對若干個不相交集合,可以實現較快的兩種操做:合併指定元素所屬的集合、查找某元素在哪一個集合裏。
 1 主要程序清單:int fa[maxn];
 2 ★ 初始化:for (i=1;i<=n;i++) fa[i]=i;//每一個元素單獨成子集:根爲序號
 3 ★ 查找元素x屬於哪一個子集:
 4 int find(int x)   //查找元素x屬於哪一個子集,同時進行「路徑壓縮」
 5 {    if (fa[x]!=x) fa[x]=find(fa[x]);  
 6     return fa[x]; //注意:若試題要求嚴格「父子」關係,則不能路徑壓縮
 7 }
 8 ★ 合併「元素x所在集合」和「元素y所在集合」:
 9 void un(int x,int y)    // union 是系統已經存在的子函數名,建議不要重名。
10 {    int rx,ry;
11     rx=find(x);ry=find(y);  // 查找各自所在的子集編號
12     if(rx!=ry) fa[rx]=ry;   //若編號不一樣,則不要同一集合,進行「合併」。
13 }

親戚relation算法

Time Limit:5000MS  Memory Limit:65536K數據結構

Description 函數

  或許你並不知道,你的某個朋友是你的親戚。他多是你的曾祖父的外公的女婿的外甥女的表姐的孫子。若是能獲得完整的家譜,判斷兩我的是不是親戚應該是可行的,但若是兩我的的最近公共祖先與他們相隔好幾代,使得家譜十分龐大,那麼檢驗親戚關係實非人力所能及。在這種狀況下,最好的幫手是計算機。
  爲了將問題簡化,你將獲得一些親戚關係的信息,如同Xuebin和Grant是親戚,Grant和Tension是親戚等,從這些信息中,你能夠推出xuebin和Tension是親戚。請寫一個程序,對於咱們的關於親戚關係的提問,以最快的速度給出答案。
spa

Input code

輸入由兩部分組成:
第一部分以N、M開始。N爲問題涉及到的人的個數(1≤N≤20 000)。這些人的編號爲一、二、三、…、N。
 下面有M行(1≤M≤1 000 000),每行有兩個數ai、bi,表示已知ai和bi是親戚。
第二部分以Q開始。如下Q行有Q個詢問(1≤Q≤1 000 000),每行爲ci、di,表示詢問ci和di是否爲親戚。
blog

Output ip

對於每一個詢問ci、di,輸出一行:若ci和di爲親戚,則輸出Yes,不然輸出No。
ci

Sample Inputit

10 7
2 4
5 7
1 3
8 9
1 2
5 6
2 3
3
3 4
7 10
8 9

Sample Outputio

Yes
No
Yes

〖實例 親戚〗 // 裸「並查集」
 1 #include<cstdio>
 2 #define MAXN 1000000 //數據大,快速讀入
 3 using namespace std;
 4 int fa[MAXN]={0};
 5 int find(int x)   // 查找x所屬集合編號
 6 {    if (fa[x]!=x) fa[x]=find(fa[x]);
 7     return fa[x];
 8 }
 9 void un(int x,int y)   //並集
10 {    int rx,ry;
11     rx=find(x);ry=find(y);  
12     if(rx!=ry) fa[rx]=ry;  
13 }
14 int main(){
15     int n,m,i,x,y,t;
16     scanf("%d%d",&n,&m);
17     for (i=1;i<=n;i++)fa[i]=i; //並查集初始化
18     for (i=1;i<=m;i++)
19     {    scanf("%d%d",&x,&y);  un(x,y);  }
20     scanf("%d",&t);
21     for (i=1;i<=t;i++)    {
22         scanf("%d%d",&x,&y);
23         if (find(x)==find(y)) printf("Yes\n");
24         else printf("No\n");
25     }
26 return 0; } 
27  
相關文章
相關標籤/搜索