-
路径压缩是常用的方法,把一颗树的层高扁平化到1层,实现高效率。
因为在并查集中,我们并不关心一棵树中,谁在谁的下面,我们只关心他们的祖先是谁。也就是根节点,那不如都挂到根节点下面。查询起来就是O(1)的时间复杂度。 -
而按秩优化,比的是谁的体系更加庞大,节点数量少的挂入节点数量多的门下。这样能极大程度地防止树退化成链表。但是在路径压缩面前,按秩优化所能产生的进一步效益并不高,而且代码实现更复杂。通常只用路径压缩算法足矣。
并查集模板:(路径压缩+按秩优化)
struct UnionSet {
int fa[MAX_N + 5], size[MAX_N + 5];
void init(int n) {
for (int i = 1; i <= n; i++) {
fa[i] = i;
size[i] = 1;
}
}
int get(int x) {
return (fa[x] = (x == fa[x] ? x : get(fa[x])));
}
void merge(int a, int b) {
int aa = get(a), bb = get(b);
if (size[aa] < size[bb]) swap(aa, bb);
fa[bb] = aa;
size[aa] += size[bb];
}
};
完整代码:
#include<iostream>
using namespace std;
#define MAX_N 10000
struct UnionSet {
int fa[MAX_N + 5], size[MAX_N + 5];
void init(int n) {
for (int i = 1; i <= n; i++) {
fa[i] = i;
size[i] = 1;
}
}
int get(int x) {
return (fa[x] = (x == fa[x] ? x : get(fa[x])));
}
void merge(int a, int b) {
int aa = get(a), bb = get(b);
if (size[aa] < size[bb]) swap(aa, bb);
fa[bb] = aa;
size[aa] += size[bb];
}
};
UnionSet u;
int main() {
int n, m;
cin >> n >> m;
u.init(n);
for (int i = 0; i < m; i++) {
int a, b, c;
cin >> a >> b >> c;
if (a == 1) u.merge(b, c);
else if (a == 2) {
cout << (u.get(b) == u.get(c) ? "Yes" : "No") << endl;
}
}
return 0;
}