并查集基础

定义

并查集是高效维护、合并集合快速查询两点连通关系树形数据结构。

可以动态维护

作用

定义包含了。

用法

查询老大

老大:可以理解为树根,代表整个连通块,在这里是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;
}

也不是很难写吧?

posted @ 2026-04-24 22:50  PCMSFV  阅读(7)  评论(0)    收藏  举报