原文:并查集从入门到出门 (opens new window)
class UnionFind {
/**
* @param {number[]} parent
*/
constructor(parent) {
this.parent = parent;
const n = this.parent.length;
this.size = new Array(n).fill(1);
this.rank = new Array(n).fill(1);
}
/**
* 直接查找
* @param {number} x
* @returns {number}
*/
findDirect(x) {
if (this.parent[x] === x) return x;
return this.findDirect(this.parent[x]);
}
/**
* 带路径压缩的查找
* @param {number} x
* @returns {number}
*/
find(x) {
if (this.parent[x] === x) return x;
this.parent[x] = this.find(this.parent[x]);
return this.parent[x];
}
/**
* 直接求并
* @param {number} x
* @param {number} y
*/
unionDirect(x, y) {
const xRoot = this.find(x);
const yRoot = this.find(y);
if (xRoot !== yRoot) {
this.parent[yRoot] = xRoot;
}
}
/**
* 按大小求并
* @param {number} x
* @param {number} y
*/
unionBySize(x, y) {
const xRoot = this.find(x);
const yRoot = this.find(y);
if (xRoot !== yRoot) {
if (this.size[yRoot] <= this.size[xRoot]) {
this.parent[yRoot] = xRoot;
this.size[xRoot] += this.size[yRoot];
} else {
this.parent[xRoot] = yRoot;
this.size[yRoot] += this.size[xRoot];
}
}
}
/**
* 按秩求并
* @param {number} x
* @param {number} y
*/
unionByRank(x, y) {
const xRoot = this.find(x);
const yRoot = this.find(y);
if (xRoot !== yRoot) {
if (this.rank[yRoot] <= this.rank[xRoot]) {
this.parent[yRoot] = xRoot;
} else {
this.parent[xRoot] = yRoot;
}
if (this.rank[xRoot] === this.rank[yRoot]) {
this.rank[xRoot]++;
}
}
}
}
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
72
73
74
75
76
77
78
79
80
81
82
83
84
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
72
73
74
75
76
77
78
79
80
81
82
83
84