并查集基础
定义
并查集是高效维护、合并集合并快速查询两点连通关系的树形数据结构。
可以动态维护。
作用
定义包含了。
用法
查询老大
老大:可以理解为树根,代表整个连通块,在这里是find()函数的返回值。
大哥可以理解为父节点,id[x]便是查找x的父节点。
int find(int x) {
if (id[x] == x)
return x;
else
return id[x] = find(id[x]);
}
id[x] = find(id[x])可以拆解为:
id[x] = find(id[x]);
return id[x];
这样写的目的是让后面查询老大的过程中只要\(O(1)\),第一次最坏是\(O(n)\)(链)
查询两点是否连通
if (find(u) == find(v)) {
cout << "Yes" << '\n';
} else {
cout << "No" << '\n';
}
插入一条边
inline void merge(int x, int y) {
int px = find(x), py = find(y);
if (px == py) return; // 本来就一样
id[px] = py; // 也就是让一个老大,变为另一个的大哥,也就是新老大
}
启发式合并
简单来说,就是让大连通块的老大当小的连通块的老大的老大,这样可以让移动次数变少
代码
#include <bits/stdc++.h>
using namespace std;
constexpr int N = 1e6 + 2;
int id[N], sz[N];//sz就是记录连通块大小的
int find(int x) {
if (id[x] == x)
return x;
else
return id[x] = find(id[x]);
}
inline void merge(int x, int y) {
int px = find(x), py = find(y);
if (px == py) return;
id[px] = py;
if (sz[px] > sz[py]) swap(px, py);
id[px] = py;
sz[py] += sz[px];
}
inline void solve() {
int op, u, v;
cin >> op >> u >> v;
if (op == 1) {
merge(u, v);
} else {
if (find(u) == find(v)) {
cout << "Y" << '\n';
} else {
cout << "N" << '\n';
}
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int n, T;
cin >> n >> T;
for (int i = 1; i <= n; i++) {
id[i] = i;
sz[i] = 1;
}
while (T--) {
solve();
}
return 0;
}
也不是很难写吧?

浙公网安备 33010602011771号