並查集 程序=數據結構+算法。 並查集是一種數據結構:針對若干個不相交集合,可以實現較快的兩種操做:合併指定元素所屬的集合、查找某元素在哪一個集合裏。
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