多个元素,分别属于不同的集合。要反复查找其中的特定的元素时,速度可能较慢。因此所采用的一种算法。
并查集时间复杂度为O(n).
主要用于:
1.判断图的连通性(最小生成树)
2.判断联通块
A题:
Input
Output
Sample Input
Sample Output
1 #include <iostream> 2 #include <stdlib.h> 3 #include <stdio.h> 4 #include <string.h> 5 6 #define MAX 100010 7 8 using namespace std; 9 int fa[MAX]; 10 int vis[MAX]; 11 12 13 int find(int x) 14 { 15 return x == fa[x] ? x : fa[x] = find(fa[x]) ; 16 } 17 18 int main() 19 { 20 int a , b; 21 memset(fa,-1,MAX * sizeof(int)); 22 memset(vis,0,MAX * sizeof(int)); 23 int flag = 1; 24 while(1) 25 { 26 scanf("%d%d",&a,&b); 27 if (a < 0 && b < 0) 28 { 29 break; 30 } 31 if (a == 0 && b == 0) 32 { 33 if (flag == 0) cout << "No" <<endl; 34 else 35 { 36 int key = 0; 37 int temp = -1; 38 for (int i = 0; i < MAX; ++i) 39 { 40 if (vis[i]) 41 { 42 if(temp < 0) temp = find(i); 43 else if (temp != find(i)) { key = 1 ; break;} 44 } 45 } 46 if(key) cout << "No" <<endl; 47 else cout << "Yes" <<endl; 48 49 } 50 51 memset(fa,-1,MAX * sizeof(int)); 52 memset(vis,0,MAX * sizeof(int)); 53 flag = 1; 54 continue; 55 56 } 57 58 if (fa[a] < 0) 59 { 60 vis[a] = 1; 61 fa[a] = a; 62 } 63 if (fa[b] < 0 ) 64 { 65 vis[b] = 1; 66 fa[b] = b; 67 } 68 69 if (find(a) != find(b)) 70 { 71 find(a) < find(b) ? fa[find(b)] = find(a) : fa[find(a)] = find(b); 72 } 73 else if(find(a) == find(b)) flag = 0; 74 75 76 77 78 } 79 return 0; 80 81 }
坑点: 题目中要求只有一个联通,如果没有将所有的点全部连起来,也是NO。
Input
Output
Sample Input
Sample Output
1 #include <iostream> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #define MAX 1010 6 int fa[MAX]; 7 using namespace std; 8 9 int find(int x) 10 { 11 return x == fa[x] ? x : fa[x] = find(fa[x]); 12 } 13 14 15 16 int main() 17 { 18 int n; 19 while(~scanf("%d",&n)) 20 { 21 for(int i = 0 ; i < n ; i++) 22 { 23 int tablenum = 0; 24 int num; 25 int cases; 26 scanf("%d%d",&num,&cases); 27 for(int j = 1; j <= num ; j++) 28 { 29 fa[j] = j; 30 } 31 tablenum = num; 32 33 for (int k = 0; k < cases; ++k) 34 { 35 int a , b; 36 scanf("%d%d",&a,&b); 37 if (find(a) != find(b)) 38 { 39 find(a) < find(b) ? fa[find(b)] = find(a) : fa[find(a)] = find(b); 40 tablenum--; 41 } 42 43 } 44 45 46 cout << tablenum <<endl; 47 48 49 } 50 } 51 return 0; 52 }
C题:
Description
Input
Output
Sample Input
100 4
2 1 2
5 10 13 11 12 14
2 0 1
2 99 2
200 2
1 5
5 1 2 3 4 5
1 0
0 0
Sample Output
4
1
1
由于初始的感染者已经被确定。所以我们每次都以小标号的人为大标号的人为father,最后只要遍历一遍所有人。find(a) == 0 就能确定a为患者。
1 #include <iostream> 2 #include <string.h> 3 #include <stdio.h> 4 #define MAX 30010 5 6 int fa[MAX]; 7 8 using namespace std ; 9 10 int find(int x) 11 { 12 return x == fa[x] ? x : fa[x] = find(fa[x]); 13 } 14 15 16 int main() 17 { 18 int N,M; 19 while(1) 20 { 21 scanf("%d%d",&N,&M); 22 if(!N && !M) break; 23 for(int m = 0 ; m < N ; m++) fa[m] = m; 24 int ans = 0; 25 for (int i = 0; i < M; ++i) 26 { 27 int n; 28 scanf("%d",&n); 29 //////// 30 int a ; 31 int b ; 32 scanf("%d",&a); 33 for (int k = 1; k < n; ++k) 34 { 35 scanf("%d",&b); 36 if (find(a) != find(b)) 37 { 38 find(a) < find(b) ? fa[find(b)] = find(a) : fa[find(a)] = find(b); 39 } 40 a = b; 41 42 } 43 44 } 45 for(int m = 0 ; m < N ; m++) 46 { 47 if (find(m) == 0) 48 { 49 ans++; 50 } 51 } 52 cout << ans <<endl; 53 } 54 return 0; 55 }
原文:http://www.cnblogs.com/ticsmtc/p/4962629.html