并查集及经典问题
Quick-Find 算法
- 联通判断 O(1)
- 合并操作 O(n)
// 染色法
class UnionSet {
public:
int *color, n;
UnionSet(int n) : n(n) {
color = new int[n + 1];
for (int i = 0; i <= n; ++i) {
color[i] = i;
}
}
int find(int x) {
return color[x];
}
void merge(int a, int b) {
int cb = color[b];
for (int i = 0; i <= n; ++i) {
if (color[i] == cb) {
color[i] = color[a];
}
}
return;
}
};
Quick-Union 算法
联通判断 tree-height 树高
合并操作 tree-height 树高
优化
- 树的高度
- 节点数量
// 将连通关系转换为树形结构,通过递归的方式快速判定
class UnionSet {
public:
int *boss, n;
UnionSet(int n) : n(n) {
boss = new int[n + 1];
for (int i = 0; i <= n; ++i) {
boss[i] = i;
}
}
int find(int x) {
if (boss[x] == x) { return x; }
return find(boss[x]);
}
void merge(int a, int b) {
int fa = find(a), fb = find(b);
if (fa == fb) { return; }
boss[fa] = fb;
return;
}
};
Weighted-Quick-Union 算法
- 判断节点数量
- 通过考虑平均查找次数的方式,对合并过程进行优化
// 通过考虑平均查找次数的方式,对合并过程进行优化。
class UnionSet {
public:
int *fa, *size, n;
UnionSet(int n) : n(n) {
fa = new int[n + 1];
size = new int[n + 1];
for (int i = 0; i <= n; ++i) {
fa[i] = i;
size[i] = 1;
}
}
int find(int x) {
if (fa[x] == x) { return x; }
return find(fa[x]);
}
void merge(int a, int b) {
int ra = find(a), rb = find(b);
if (ra == rb) { return; }
if (size[ra] < size[rb]) {
fa[ra] = rb;
size[rb] += size[ra];
} else {
fa[rb] = ra;
size[ra] += size[rb];
}
return;
}
};
路径压缩 Weighted-Quick-Union 算法
- 把所有节点挂到根节点上(扁平化管理)
// 修改find操作
class UnionSet {
public :
int *fa, *size, n;
UnionSet(int n) : n(n) {
fa = new int[n + 1];
size = new int[n + 1];
for (int i = 0; i <= n; i++) {
fa[i] = i;
size[i] = 1;
}
}
int find(int x) {
if (fa[x] == x) { return x; }
int root = find(fa[x]);
fa[x] = root;
return root;
}
void merge(int a, int b) {
int ra = find(a), rb = find(b);
if (ra == rb) { return; }
if (size[ra] < size[rb]) {
fa[ra] = rb;
size[rb] += size[ra];
} else {
fa[rb] = ra;
size[ra] += size[rb];
}
return;
}
};
带路径压缩的并查集模板
class UnionFind {
constructor(n) {
this.boss = new Array(n).fill(0).map((val, ind) => ind);
this.size = new Array(n).fill(1);
}
get(x) {
return (this.boss[x] = this.boss[x] == x ? x : this.get(this.boss[x]));
}
merge(a, b) {
this.boss[this.get(a)] = this.get(b);
}
}