并查集
简单版本
void solve() {
int n, m;
cin >> n >> m;
vector<int> fa(n + 1);
// init
iota(fa.begin(), fa.end(), 0);
// 找父亲
function<int(int)> find = [&](int x) {
return fa[x] == x ? x : fa[x] = find(fa[x]);
};
// 合并
auto merge = [&](int x, int y) {
fa[find(x)] = find(y);
};
while (m--) {
int q, x, y;
cin >> q >> x >> y;
if (q == 1) {
merge(x, y);
} else {
cout << ((find(x) == find(y)) ? "Y" : "N") << endl;
}
}
}
启发式合并
void solve() {
int n, m;
cin >> n >> m;
vector<int> fa(n + 1), sz(n + 1, 1);
iota(fa.begin(), fa.end(), 0);
// 找父亲
function<int(int)> find = [&](int x) {
return fa[x] == x ? x : fa[x] = find(fa[x]);
};
// 启发式合并
auto merge = [&](int x, int y) {
int fx = find(x), fy = find(y);
if (fx == fy) {
return;
}
if (sz[fx] < sz[fy]) {
swap(fx, fy);
}
fa[fy] = fx;
sz[x] += sz[y];
};
while (m--) {
int q, x, y;
cin >> q >> x >> y;
if (q == 1) {
merge(x, y);
} else {
cout << ((find(x) == find(y)) ? "Y" : "N") << endl;
}
}
}
删除与移动
删除:将父亲设为自己,为了保证删除的元素都是叶节点,设置副本并初始化父亲为副本。 移动:保重移动的元素都在叶子节点。
实现以下功能:
- 合并两个元素所处集合。
- 移动 到 集合。
- 查询元素所在集合大小和元素和。
void solve() {
int n, m;
if (!(cin >> n >> m)) {
exit(0);
}
vector<int> fa((n + 1) * 2), sz((n + 1) * 2, 1);
vector<int> su((n + 1) * 2); // 添加统计大小
// 初始化
iota(fa.begin(), fa.begin() + n + 1, n + 1);
iota(fa.begin() + n + 1, fa.end(), n + 1);
iota(su.begin() + n + 1, su.end(), 0);
// 找父亲
function<int(int)> find = [&](int x) {
return fa[x] == x ? x : fa[x] = find(fa[x]);
};
// 启发式合并(按大小)
auto merge = [&](int x, int y) {
int fx = find(x), fy = find(y);
if (fx == fy) {
return;
}
if (sz[fx] < sz[fy]) {
swap(fx, fy);
}
fa[fy] = fx;
sz[fx] += sz[fy];
su[fx] += su[fy];
};
// 删除
auto remove = [&](int x) {
--sz[find(x)];
fa[x] = x;
};
// 移动
auto move = [&](int x, int y) {
auto fx = find(x), fy = find(y);
if (fx == fy) {
return;
}
fa[x] = fy;
--sz[fx], ++sz[fy];
su[fx] -= x, su[fy] += x;
};
while (m--) {
int q;
cin >> q;
if (q == 1) {
int x, y;
cin >> x >> y;
merge(x, y);
} else if (q == 2) {
int x, y;
cin >> x >> y;
move(x, y);
} else if (q == 3) {
int x;
cin >> x;
int fx = find(x);
cout << sz[fx] << ' ' << su[fx] << endl;
}
}
}