C++并查集:高效解决连通性问题

一、前言

C++ 语法、面向对象、STL 已经全部收官。从今天开始,正式进入高阶数据结构与算法深耕 。首篇先学并查集:结构简单、代码短、考点极多、适用场景非常广。

二、并查集是什么

并查集(Disjoint Set Union,DSU)三个核心操作:

  1. 合并:把两个集合合并成一个
  2. 查找:找某个元素的根节点
  3. 判连通:判断两个元素是否在同一个集合

形象理解:每个人是一个节点,认识的人归为一个圈子 ,并查集就是用来管理圈子、合并圈子、查是否同圈

三、并查集核心思想

  • 每个节点有一个父节点 parent \[\]
  • 根节点:自己的父节点是自己
  • 找祖先:一路往上找,直到父节点等于自身
  • 合并集合:把一个集合的根,挂到另一个集合根下面

四、基础朴素版并查集

1. 初始化

每个人初始自己是一个集合,父节点等于自己

复制代码
const int N = 1005;
int parent[N];

// 初始化
void init(int n)
{
    for(int i = 1; i <= n; i++)
    {
        parent[i] = i;
    }
}

2. 查找根节点

复制代码
int find(int x)
{
    if(parent[x] == x) 
        return x;
    return find(parent[x]);
}

3. 合并两个集合

复制代码
void unite(int x, int y)
{
    int fx = find(x);
    int fy = find(y);
    if(fx != fy)
    {
        parent[fy] = fx;
    }
}

4. 判断是否连通

复制代码
bool isSame(int x, int y)
{
    return find(x) == find(y);
}

五、优化一:路径压缩(必加)

朴素版查找层数多、效率低。路径压缩:查找时把沿途所有节点直接挂到根节点,下次查找 O (1)。

优化后 find 函数:

复制代码
int find(int x)
{
    if(parent[x] == x)
        return x;
    // 路径压缩:递归回溯直接指向根
    parent[x] = find(parent[x]);
    return parent[x];
}

刷题默认必写路径压缩

六、优化二:按秩合并(可选)

维护树的高度 / 节点数量,合并时小树挂大树 ,防止树过高。日常刷题只写路径压缩就够用,竞赛再加上按秩合并。

七、并查集完整万能模板(可直接复制刷题)

复制代码
#include <iostream>
using namespace std;

const int N = 1005;
int parent[N];

// 初始化
void init(int n)
{
    for(int i = 1; i <= n; ++i)
        parent[i] = i;
}

// 查找 + 路径压缩
int find(int x)
{
    if(parent[x] != x)
        parent[x] = find(parent[x]);
    return parent[x];
}

// 合并
void unite(int x, int y)
{
    x = find(x);
    y = find(y);
    if(x != y)
        parent[y] = x;
}

// 判断同集合
bool same(int x, int y)
{
    return find(x) == find(y);
}

int main()
{
    int n,m;
    cin >> n >> m;
    init(n);

    while(m--)
    {
        int op,x,y;
        cin >> op >> x >> y;
        if(op == 1)
            unite(x,y);
        else
        {
            if(same(x,y)) cout << "Yes\n";
            else cout << "No\n";
        }
    }
    return 0;
}

八、经典适用场景

  1. 判断图中两点是否连通
  2. 朋友圈、亲戚关系合并
  3. 最小生成树 Kruskal 算法必备
  4. 岛屿数量、连通块统计
  5. 区间合并、分组问题

九、今日核心总结

  1. 并查集三大操作:初始化、查找、合并
  2. 路径压缩是标配优化,极大提升效率
  3. 模板固定,刷题直接套用即可
  4. 常用于连通性判断、集合合并、图论基础题

十、课后练习

  1. 手写并查集模板,实现 5 个元素合并、判断连通
  2. 输入多组关系,统计最终有多少个独立连通块
相关推荐
KaMeidebaby3 小时前
卡梅德生物技术快报|PD1 单克隆抗体定制配套 N 糖全谱质控开发
前端·人工智能·算法·数据挖掘·数据分析
8Qi84 小时前
LeetCode 235. 二叉搜索树的最近公共祖先(LCA)
算法·leetcode·二叉树·递归·二叉搜索树·lca·迭代
好评1244 小时前
【C++】智能指针全解
c++·智能指针
bIo7lyA8v5 小时前
算法稳定性分析中的随机扰动建模的技术8
算法
是阿建吖!5 小时前
【Linux】信号
android·linux·c语言·c++
城北徐宫5 小时前
Linux信号深度解剖:5种产生、3张表、4次切换
linux·c++·学习
liulilittle5 小时前
论 Linux 内核态全局稳态带宽的卡尔曼估计与工程实现
linux·服务器·网络·c++·计算机网络·tcp·通信
XBodhi.5 小时前
Visual Studio C++ 语法错误: 缺少“;”(在“return”的前面)
开发语言·c++·visual studio
科研online5 小时前
基于多源数据和XGBoost-SHAP分析中国大陆绿地碳汇空间变异影响因素的非线性相关性与尺度差异
算法·学习方法
Cthy_hy5 小时前
拓扑排序超详解:原理 + Kahn 贪心算法
python·算法·贪心算法