继月赛出了道可删除并查集后,又做了几道可删除并查集的题,发现之前的代码有点小问题。
可删除并查集的基本原理是设置一个虚点,也就是说一个点删除了,那么他对应的值就不再是之前的那一个点,而是变成了其他点。
即可删除并查集通过id映射的关系查找我的点在哪里。
有几个问题就是初始化时必须要把(n + m)个点的父亲结点都设置为本身,(n是点个数,m是操作次数)
然后关于查询父亲结点的操作,必须通过id去映射。
对于删去的点,其实原来的点还是存在的。如果说2的父亲是1,且1被删除,那么查询2的父亲返回的是1,查询2的父亲,返回的是n+第几次操作。
但是不影响。主要是我想去查找这个点的真正父亲结点到底是哪个不太行。
模板
struct DSU{
int fa[N << 1], rnk[N << 1], id[N << 1], tot;
int find_(int x){ // 其他地方访问find都要用find(id[x])
return x == fa[x] ? x : fa[x] = find_(fa[x]);
}
int find(int x) { // 查询x的父亲结点
return find_(id[x]);
}
void move(int x){ // 把点x从集合里删除
int fx = find(x);
rnk[fx]--;
id[x] = ++tot;
}
void init(int n, int m){
tot = n;
for(int i = 1; i <= n + m; i++) fa[i] = id[i] = i, rnk[i] = 1;
}
void unit(int x, int y){ // 合并x和y
int fx = find(x), fy = find(y);
if(fx != fy) {
fa[fx] = fy;
rnk[fy] += rnk[fx];
}
}
} dsu;