使用并查集判断图中是否含有环
1 // function:
2 // 使用并查集判断图中是否含有环
3 // 须知:parent[x1] = x2 表示顶点x1的父节点是x2
4 #include<iostream>
5 using namespace std;
6
7 #define VERTICES 6
8
9 // 初始化
10 void initialize(int parent[], int rank[]){
11 for(int i=0; i < VERTICES; i++){
12 parent[i] = -1;// 初始化每个顶点的父节点是-1
13 rank[i] = 0;// 用来路径压缩
14 }
15 }
16
17 // 查找节点的根
18 int find_root(int x, int parent[]){
19 int x_root = x;
20 while(parent[x_root] != -1){
21 x_root = parent[x_root];
22 }
23 return x_root;
24 }
25
26 // 集合合并
27 int union_vertices(int x, int y, int parent[], int rank[]){
28 // 1 -- 合并成功
29 // 0 -- 合并失败,即x,y已经在同一个集合内
30 int x_root = find_root(x, parent);
31 int y_root = find_root(y, parent);
32 if(x_root == y_root)
33 return 0;
34 else{ // 路径压缩
35 if(rank[x_root] > rank[y_root])
36 parent[y_root] = x_root;
37 else if(rank[x_root] < rank[y_root])
38 parent[x_root] = y_root;
39 else{
40 parent[x_root] = y_root;
41 rank[y_root]++;
42 }
43 return 1;
44 }
45 }
46
47 int main(int argc, char const *argv[]) {
48 int parent[VERTICES];
49 int rank[VERTICES];
50 /* 代码中的图如下所示,1, 3, 4, 2组成一个环
51 * 0
52 * \
53 * 1
54 * / \
55 * 2 3
56 * | \ |
57 * 5 4
58 */
59 int edges[6][2] = { {0, 1}, {1, 2}, {1, 3},
60 {2, 5}, {3, 4}, {2, 4} };// 图中所有的边集合
61 initialize(parent, rank);
62 for(int i=0; i < 6; ++i){
63 int x = edges[i][0];
64 int y = edges[i][1];
65 if(union_vertices(x, y, parent, rank) == 0){
66 cout<<"Cycle detected."<<endl;
67 return 0;
68 }
69 }
70 cout<<"No cycle."<<endl;
71 return 0;
72 }
运行结果:
Cycle detected.
[Finished in 1.1s]
参考资料:
黄浩杰,并查集(Disjoint-set union),youtube