并查集(Disjoint-set Union,DSU),也称作不相交集合数据结构,是一种用来管理元素分组的数据结构。它主要支持两种操作:查找(Find)和合并(Union)。查找操作用于确定某个元素属于哪个组,而合并操作则用于将两个组合并成一个。
以下是一个简单的并查集的 C++ 实现:
#include <iostream>
#include <vector>
class UnionFind {
private:
std::vector<int> parent; // 存储每个节点的父节点
std::vector<int> rank; // 存储每个根节点的秩(树的高度)
public:
// 构造函数:初始化并查集,将每个元素的父节点设为自身,秩设为 0
UnionFind(int n) : parent(n), rank(n, 0) {
for (int i = 0; i < n; ++i) {
parent[i] = i;
}
}
// 查找操作:返回元素 x 所在组的根节点
int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]); // 路径压缩
}
return parent[x];
}
// 合并操作:将元素 x 所在的组和元素 y 所在的组合并
void merge(int x, int y) {
int rootX = find(x);
int rootY = find(y);
if (rootX != rootY) {
// 将秩较小的根节点连接到秩较大的根节点上
if (rank[rootX] < rank[rootY]) {
parent[rootX] = rootY;
} else if (rank[rootX] > rank[rootY]) {
parent[rootY] = rootX;
} else {
parent[rootY] = rootX;
rank[rootX]++;
}
}
}
// 检查两个元素是否属于同一个组
bool isConnected(int x, int y) {
return find(x) == find(y);
}
};
int main() {
int n = 5;
UnionFind uf(n);
// 合并一些组
uf.merge(0, 1);
uf.merge(2, 3);
uf.merge(0, 4);
// 检查一些元素是否属于同一个组
std::cout << "Is 1 connected to 4? " << std::boolalpha << uf.isConnected(1, 4) << std::endl;
std::cout << "Is 2 connected to 3? " << std::boolalpha << uf.isConnected(2, 3) << std::endl;
return 0;
}
在这个示例中,我们定义了一个 UnionFind
类来实现并查集。它包含了 parent
和 rank
两个私有成员变量,分别用来存储每个元素的父节点和每个根节点的秩。构造函数用来初始化并查集,将每个元素的父节点设为自身,秩设为 0。find()
函数用来查找某个元素所在组的根节点,并进行路径压缩优化。merge()
函数用来将两个组合并,它首先找到两个元素所在组的根节点,然后根据秩的大小合并。isConnected()
函数用来检查两个元素是否属于同一个组。