并查集, 从这个名字上也可以知道是合并和查找集合的, 它也叫不相交的集的数据结构, 典型的例题有食物链, 来判断有多少个独立的树什么的, 下面一个例题,来简单的解释并查集:一个犯罪团伙一共有n个人, 现在只知道谁跟谁一伙, 来求出一共有多少个团伙, 代码如下:
1 #include <stdio.h> 2 //并查集 3 /*此案例是给定总个数, 从1到n, 然后给定谁和谁是一伙的, 4 输入一个m来确定一个有多少个一伙的, 求出最后一个有几伙*/ 5 int f[1000], n, m, k, sum = 0; 6 //初始化 7 void init() 8 { 9 for(int i = 1; i <= n; i++) 10 f[i] = i; 11 } 12 //找到它的父亲 13 int getf(int i) 14 { 15 if(i != f[i]) 16 { 17 f[i] = getf(f[i]);//路径压缩 18 } 19 return f[i]; 20 } 21 //合并函数, 22 void merge(int i, int j) 23 { 24 int t1 = getf(i); 25 int t2 = getf(j); 26 if(t1 != t2) 27 { 28 f[t2] = t1; 29 } 30 } 31 32 int main() 33 { 34 // freopen("1.in", "r", stdin); 35 scanf("%d ", &n); 36 init(); 37 int m; 38 scanf("%d ", &m); 39 int x, y; 40 for(int i = 1; i <= m; i++) 41 { 42 scanf("%d %d", &x, &y); 43 merge(x, y); 44 } 45 for(int i = 1; i <= n; i++) 46 { 47 if(f[i] == i) 48 sum++; 49 } 50 printf("%d ", sum); 51 return 0; 52 }
测试数据:
10 9
1 2
3 4
5 2
4 6
2 6
8 7
9 7
1 6
2 4
结果如下:
练习题:http://acm.hdu.edu.cn/showproblem.php?pid=1232
1 #include<iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 const int N = 1004; 6 int father[N]; 7 void init() 8 { 9 for (int i = 1; i < N; i++) 10 father[i] = i; 11 } 12 13 int find(int x) 14 { 15 if (x != father[x]) 16 father[x] = find(father[x]);//路径压缩 17 return father[x]; 18 } 19 void union_set(int a, int b)//合并 20 { 21 int ta = find(a); 22 int tb = find(b); 23 if (ta < tb) 24 father[tb] = ta; 25 else if (ta > tb) 26 father[ta] = tb; 27 } 28 int main() 29 { 30 int n, m; 31 while (~scanf("%d", &n) && n) 32 { 33 scanf("%d", &m); 34 init(); 35 int a, b; 36 for (int i = 0; i < m; i++) 37 { 38 scanf("%d %d", &a, &b); 39 union_set(a, b); 40 } 41 int num = 0; 42 for (int i = 1; i <= n; i++) 43 if (father[i] == i)//找连通分量的个数 44 num++; 45 printf("%d ", num - 1); 46 47 } 48 return 0; 49 }