并查集

  • 并查集用来表示各节点间的连通关系;
  • 有些问题可以抽象用并查集来解决;
  • 节点用数组表示!!!

基本

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
class UnionFind {
private:
// 连接分量的数目
int count;

// 记录每个节点的父节点
vector<int> parent;
public:
UnionFind(int n) : count(n) {
parent.resize(n);
for (int i = 0; i < n; ++i) {
parent[i] = i;
}
}

int Count() {
return count;
}

// 找到该节点所在树的根节点
int findRoot (int x) {
while (x != parent[x]) {
x = parent[x];
}
return x;
}

// 连接两个节点
void unionIt(int p, int q) {
int rootP = findRoot(p);
int rootQ = findRoot(q);
if (rootP == rootQ) return;

parent[rootP] = rootQ;
--count;
}

// 确认两个节点是否连接
bool isConnected(int p, int q) {
int rootP = findRoot(p);
int rootQ = findRoot(q);
return rootP == rootQ;
}
};

优化

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
class UnionFind {
private:
// 连接分量的数目
int count;
// 记录每棵树的节点个数
vector<int> size;
// 记录每个节点的父节点
vector<int> parent;
public:
UnionFind(int n) : count(n) {
parent.resize(n);
size.resize(n);
for (int i = 0; i < n; ++i) {
parent[i] = i;
size[i] = 1;
}
}

int Count() {
return count;
}

// 找到该节点所在树的根节点
int findRoot (int x) {
while (x != parent[x]) {
// 路径压缩
parent[x] = parent[parent[x]];
x = parent[x];
}
return x;
}

// 连接两个节点
void unionIt(int p, int q) {
int rootP = findRoot(p);
int rootQ = findRoot(q);
if (rootP == rootQ) return;

// 小树接在大树之下,更平衡
if (size[rootP] >= size[rootQ]) {
parent[rootQ] = rootP;
size[rootP] += size[rootQ];
} else {
parent[rootP] = rootQ;
size[rootQ] += size[rootP];
}
--count;
}

// 确认两个节点是否连接
bool isConnected(int p, int q) {
int rootP = findRoot(p);
int rootQ = findRoot(q);
if (rootP == rootQ) return true;
else return false;
}
};

并查集
http://example.com/2022/07/02/并查集/
作者
ZYUE
发布于
2022年7月2日
更新于
2022年7月31日
许可协议