并查集
并查集也称为不相交集数据结构。其目的是找出元素之间的关系并归为若干个集合。
题目示例:
某地的警察发现几条关于犯罪分子的线索,求当地有几个独立的犯罪团伙:
数据给出格式如下:
1 2 3 4 5 6 7 8 9 10 11
| 11 10 1 2 3 4 5 2 4 6 2 6 7 11 8 7 9 7 9 11 1 6
|
- 第一行两个数字a b,表示有a个犯罪分子和b条线索
- 第二行开始有b行线索,每行两个数字a b,表示a 和 b两个犯罪分子是团伙
- 注意,团伙的团伙也是团伙
利用并查集让团伙的两个犯罪分子”归顺“其中一个,默认右边归顺左边,即靠左原则
解题代码
整体代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| #include<iostream> using namespace std;
int peo, clue;
int getFather(int* arr,int v) { if (arr[v] == v) { return v; } else { arr[v] = getFather(arr, arr[v]); return arr[v]; } }
void merge(int* arr, int v, int u) { int t1 = getFather(arr, v); int t2 = getFather(arr, u);
if (t1 != t2) { arr[t2] = t1; } return; }
int main() { cin >> peo >> clue;
int* arr = new int[peo + 1]; for (int i = 0; i <= peo; i++) { arr[i] = i; }
int a, b; for (int i = 0; i < clue; i++) { cin >> a>> b; merge(arr, a, b); }
int num = 0; for (int i = 1; i <= peo; i++) { if (arr[i] == i) { num++; } }
cout << "一共有" << num << "个犯罪团伙" << endl; cout << "最终数组情况为:" << endl; for (int i = 1; i <= peo; i++) { cout << i << "-" << arr[i] << " "; }
return 0; }
|
核心代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| int getFather(int* arr,int v) { if (arr[v] == v) { return v; } else { arr[v] = getFather(arr, arr[v]); return arr[v]; } }
void merge(int* arr, int v, int u) { int t1 = getFather(arr, v); int t2 = getFather(arr, u);
if (t1 != t2) { arr[t2] = t1; } return; }
|
洛谷例题
亲戚
题目背景
若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系。
题目描述
规定:x 和 y 是亲戚,y 和 z 是亲戚,那么 x 和 z 也是亲戚。如果 x,y 是亲戚,那么 x 的亲戚都是 y的亲戚,y的亲戚也都是 x 的亲戚。
输入格式
第一行:三个整数 n,m,p,(n,m,p≤5000),分别表示有 n 个人,m 个亲戚关系,询问 p 对亲戚关系。
以下 m 行:每行两个数 Mi,Mj,1≤Mi, Mj≤N,表示 Mi 和 Mj 具有亲戚关系。
接下来 p 行:每行两个数 Pi,Pj,询问 Pi 和 Pj 是否具有亲戚关系。
输出格式
p 行,每行一个 Yes 或 No。表示第 i 个询问的答案为“具有”或“不具有”亲戚关系。
样例 #1
样例输入 #1
1 2 3 4 5 6 7 8 9
| 6 5 3 1 2 1 5 3 4 5 2 1 3 1 4 2 3 5 6
|
样例输出 #1
AC代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| #include<iostream> using namespace std;
int findFather(int* arr,int v) { if (arr[v] == v) { return v; } else { arr[v] = findFather(arr, arr[v]); return arr[v]; } }
int main() { int peo, clue, ques; cin >> peo >> clue >> ques; int* arr = new int[peo + 1]; int* brr = new int[ques]; int* crr = new int[ques]; for (int i = 0; i <= peo; i++) { arr[i] = i; } int a, b,f1,f2; for (int i = 0; i < clue; i++) { cin >> a >> b; f1 = findFather(arr, a); f2 = findFather(arr, b); if (f1 != f2) { arr[f2] = f1; } } bool ise = false; for (int i = 0; i < ques; i++) { cin >> brr[i] >> crr[i]; } for (int i = 0; i < ques; i++) { if (ise == false) ise = true; else cout << endl; arr[brr[i]] = findFather(arr, brr[i]); arr[crr[i]] = findFather(arr, crr[i]); if (arr[brr[i]] == arr[crr[i]]) { cout << "Yes"; } else { cout << "No"; } } return 0; }
|