普通并查集
il void init() {
for(re ll i = 1; i <= n; ++i)
fa[i] = i;
}
il ll find(ll x) {
return fa[x] == x?x : fa[x] = find(fa[x]);
}
il void merge(ll x, ll y) {
ll fx = find(x), fy = find(y);
if(fx != fy)
fa[fy] = fx;
return ;
}
eg. 星球大战
带权并查集
维护每个节点及其到根节点的距离
il void init() {
for(re ll i = 1; i <= n; ++i) {
fa[i] i;
dist[i] = 0;//到根节点的距离(一开始每个点到自己都为0)
size[i] = 1;//每个集合的大小
}
}
il ll find(ll x) {
if(fa[x] == x) return x;
ll y = fa[x];
fa[x] = find(y);
dist[x] += dist[y];
return fa[x];
}
il void merge(ll x, ll y) {
ll fx = find(x), fy = find(y);
if(fx != fy) {
fa[fx] = fy;
dist[fx] = size[fy];
size[fy] += size[fx];
}
return ;
}
种类并查集
有m种关系,用数组对应表示
il ll find(ll x) {
if(fa[x] == x) return x;
ll y = fa[x];
fa[x] = find(y);
caty[x] = (caty[x] + caty[y]) % m;
return fa[x];
}
il void merge(ll x, ll y, ll d) {
//判断x与y的关系为d是否合法
ll fx = find(x), fy = find(y);
if(fx == fy) {
//在同一集合里
if((caty[x] - caty[y] + m) % m != d)
printf("NO\n");
}else {
fa[fx] = fy;
caty[fx] = (caty[y] - caty[x] + d + m) % m;
//建立新关系
}
}