特殊并查集
普通的并查集只能实现简单的合并 (Unite)和查询(Find),而无法高效的实现转移(move)和删除(erase)。为了解决该问题,我们可以使用带虚节点的特殊并查集,在实现高效合并和查询的同时,用空间换时间,实现高效的转移和删除操作。
以下为代码实现(main函数略):
#include <iostream>
#include <vector>
using namespace std;
vector<int> pa, Size, sum;
void Init(int n) {
pa.resize(2 * n + 10);
Size.resize(2 * n + 10,1);
sum.resize(2 * n + 10);
for (int i = 1;i <= n;i++) {
pa[i] = n +
sum[n + i] = i;
}
for (int i = n + 1;i <= 2 * n;i++) {
pa[i] = i;
}
}
int Find(int x) {
if (pa[x] != x)pa[x] = Find(pa[x]);
return pa[x];
}
void unite(int x, int y) {
x = Find(x), y = Find(y);
if (x == y)return;
pa[x] = y;
Size[y]+=Size[x];
sum[y] += sum[x];
}
void move(int x,int y){
int fx = Find(x), fy = Find(y);
if (fx == fy)return;
pa[x] = fy;
Size[fy]++;
Size[fx]--;
sum[fy] += x;
sum[fx] -= x;
}
void erase(size_t x) {
size_t y = find(x);
size[y]--;
pa[x] = id++;
}
在该代码实现中,使用虚节点代替真节点承担根的位置,使得真节点都存于叶子节点,从而使树最多为两层,省略了按秩合并,在删除和转移的操作中,只需更改虚节点,不会影响其他真节点。在理解和操作上也更直观,易理解,也可在此代码的基础上进行其他扩展操作,如维护树的边权,分离集合(虽然我还不会。。。)

浙公网安备 33010602011771号