并查集(详解+例题)

1、作用

  • 将两个集合合并

  • 询问两个元素是否在一个集合中


2、基本原理

  • 每个集合用一颗树表示。树根的编号就是整个集合的编号每个节点存储它的父节点p[x]表示x的父节点。


3、实现

  • 问题1:如何判断树根:if(p[x]==x);

  • 问题2:如何求x的集合编号:while(p[x]!=x) x = p[x];(这里会优化后面,通过路径压缩优化)

  • 问题3:如何合并两个集合:p[x]是x的集合编号,p[y]是y的集合编号。p[x] = y;表述编号x的树合并到y的树根下

3.1、优化:
图解:

 通过递归回溯的形式巧妙的去让所有节点指向直接根节点。通过这个优化能让时间复杂度近乎O(1)。


代码模板:
//返回x的祖宗节点 + 路径压缩
int find(int x)
{
    /*利用递归的形式,去一直找到树的根
    非常细节的地方是,在递归回溯的时候,通过一直往上找,在找到时候
    会让所有节点都指向根节点
    */
    if(p[x]!=x) p[x] = find(p[x]);
    return p[x];
}

4、例题1:

         

AC代码: 
#include<iostream>

using namespace std;

const int N = 100010;
int n,m;
int p[N];//存储父亲节点,p[x]表示x的父亲节点
//返回x的祖宗节点 + 路径压缩
int find(int x)
{
    /*利用递归的形式,去一直找到树的根
    非常细节的地方是,在递归回溯的时候,通过一直往上找,在找到时候
    会让所有节点都指向根节点
    */
    if(p[x]!=x) p[x] = find(p[x]);
    return p[x];
}

int main()
{
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++) p[i] = i;
    while (m -- )
    {
        //这里为什么要用字符串去读入操作呢,
        //因为字符串可以帮我们去过滤掉一些空格回车什么的
        char op[2];
        int a,b;
        scanf("%s%d%d", op,&a,&b);
        if(op[0] == 'M') p[find(a)] = find(b);
        else
        {
            if(find(a) == find(b)) puts("Yes");
            else puts("No");
        }
    }
    return 0;
}

 例题2:



 AC代码:
#include<iostream>

using namespace std;

const int N = 1e5+10;
int n,m;
//存储父亲节点,p[x]表示x的父亲节点,sz存储树根连接的点的数量
int p[N],sz[N];

//返回x的祖宗节点 + 路径压缩
int find(int x)
{
    if(p[x] != x) p[x] = find(p[x]);
    return p[x];
}

int main()
{
    scanf("%d %d", &n, &m);
    for(int i=1;i<=n;i++)
    {
        p[i] = i;//存一下每个集合的根节点p指向父亲节点
        sz[i] = 1;//存一下每个集合的个数
    }
    while(m --)
    {
        char op[5];
        int a,b;
        scanf("%s",op);
        if(op[0] == 'C')
        {
            scanf("%d%d", &a, &b);
            //如果a和b已经在一起了,就不能再加了
            if(find(a) == find(b)) continue;
            //这里a,b不能换位置,因为下面的代码是连在了b书上,所以b树要加
            sz[find(b)] += sz[find(a)];
            p[find(a)] = find(b); //把编号为a的树连到编号为b的上面
        }
        else if(op[1] == '1')
        {
            scanf("%d%d", &a, &b);
            if(find(a) == find(b)) puts("Yes");
            else puts("No");
        }
        else
        {
            scanf("%d", &a);
            printf("%d\n",sz[find(a)]);
        }
    }
    return 0;
}

总结一下,本人举得并查集的关键一个在find函数,一个在我们要维护的信息!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/464146.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

WiFi7 MLO技术框架

在2019年7月份&#xff0c;关于WiFi7 MLO的开放式讨论已经基本完成了&#xff0c;关注点集中体现在band steering/balancing和multi band aggregation上面。 英特尔基于开放讨论的基础&#xff0c;提出了MLO的协议技术框架&#xff0c;尽量兼容已有的协议文本&#xff0c;并提…

大数据数据分析-scala、IDEA、jdk之间的搭配关系

Scala主要是一门面向对象编程语言和函数式编程语言。 一、大数据框架&#xff08;处理海量/流式数据&#xff09; - ---以HADOOP 2. x为系列的大数据生态系统处理框架 离线数据分析&#xff0c;分析的数据为N1天数据 -----MapReduce 并行计算框架&#xff0c;分而治之…

C语言基础数据结构——栈和队列

目录 1.栈 1.1栈的选型 1.2 实现代码 2.队列 2.1整体思路 2.2初始化和销毁 2.3出入队列 2.4取队列元素 2.5判断队列是否为空 2.6返回队列中元素个数 2.7 Test 1.栈 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。 进行数…

Docker入门二(应用部署、迁移与备份、DockerFile、docker私有仓库、Docker-Compose)

文章目录 一、应用部署1.MySQL部署2.Redis部署3.Nginx部署 二、迁移与备份1.容器做成镜像2.镜像备份和恢复(打包成压缩包&#xff09; 三、DockerFile0.镜像从哪里来&#xff1f;1.什么是DockerFile2.DockerFile 构建特征3.DockerFile命令描述4.构建一个带vim的centos镜像案例5…

Oracle Primavera Analytics 是什么,与P6的关系?

前言 Oracle Primavera P6 Analytics 是与P6有关的一个相对较新的模块&#xff0c;Primavera 用户社区在很大程度上尚未对其进行探索。 那么它到底有什么作用呢&#xff1f; 通过了解得知它旨在通过深入了解组织的项目组合绩效&#xff0c;帮助高级管理层对其项目组合做出更好…

【开源】SpringBoot框架开发就医保险管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 科室档案模块2.2 医生档案模块2.3 预约挂号模块2.4 我的挂号模块 三、系统展示四、核心代码4.1 用户查询全部医生4.2 新增医生4.3 查询科室4.4 新增号源4.5 预约号源 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVue…

MySQL | 表的约束

目录 1. 空属性 NULL 2. 默认值 DEFAULT 3. 列描述comment 4. zerofill 5. 主键 PRIMARY KEY 6. 自增长AUTO_INCREMENT 7. 唯一键UNIQUE 8. 外键 真正约束字段的是数据类型&#xff0c;但是数据类型约束很单一&#xff0c;需要有一些额外的约束&#xff0c;更好的保证数…

VS2019加QT5.14中Please assign a Qt installation in ‘Qt Project Settings‘.问题的解决

第一篇&#xff1a; 原文链接&#xff1a;https://blog.csdn.net/aoxuestudy/article/details/124312629 error:There’ no Qt version assigned to project mdi.vcxproj for configuration release/x64.Please assign a Qt installation in “Qt Project Settings”. 一、分…

AG32 MCU以太网应用实例demo

一. 前言 AGM32系列32位微控制器旨在为MCU用户提供新的自由度和丰富的兼容外设&#xff0c;以及兼容的引脚和功能。AG32F407系列产品具有卓越的品质&#xff0c;稳定性和卓越的价格价值。 AG32产品线支持其所有接口外设尽可能接近主流兼容性&#xff0c;并提供丰富的参考设计…

机器人路径规划:基于深度优先搜索(Depth-First-Search,DFS)算法的机器人路径规划(提供Python代码)

一、深度优先搜索算法介绍 深度优先搜索算法&#xff08;Depth-First-Search&#xff09;的基本思想是沿着树的深度遍历树的节点&#xff0c;尽可能深的搜索树的分支。当节点v的所有边都己被探寻过&#xff0c;搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已…

代码学习记录21--回溯算法第二天

随想录日记part21 t i m e &#xff1a; time&#xff1a; time&#xff1a; 2024.03.16 主要内容&#xff1a;今天主要是结合类型的题目加深对回溯算法的理解&#xff1a;1&#xff1a;组合总和&#xff1b;2&#xff1a;电话号码的字母组合 216.组合总和III17.电话号码的字母…

维基百科推广秘诀13个方法助你成为行业领导者-华媒舍

维基百科&#xff08;Wikipedia&#xff09;作为全球最大、最权威的在线百科全书&#xff0c;拥有海量的知识内容&#xff0c;被广大用户广泛使用。对于任何一个领域的从业者来说&#xff0c;建立自己的维基百科页面&#xff0c;无疑是提升行业影响力的重要手段。本文将向您介绍…

LEETCODE 100255. 成为 K 特殊字符串需要删除的最少字符数

整体思路: 1.可以看到这道题是要求是最小的&#xff0c;那么可以想到遍历所有情况 2.把题干已知条件转换为一个数组&#xff0c;那么只需要以数组每个元素为开头遍历所有情况即可。 3.对于一个数考虑其后面的情况&#xff0c;其后每个数等于这个数k和数本身的最小值(遍历累计求…

【C语言】指针基础知识(一)

计算机上CPU&#xff08;中央处理器&#xff09;在处理数据的时候&#xff0c;需要的数据是在内存中读取的&#xff0c;处理后的数据也会放回内存中。 一,内存和地址 内存被分为一个个单元&#xff0c;一个内存单元的大小是一个字节。 内存单元的编号&#xff08;可以理解为门…

Ypay源支付2.8.8免授权聚合免签系统

本帖最后由 renleixiaoxu 于 2024-3-15 09:46 编辑 产品介绍 XPay是专为个人站长打造的聚合免签系统&#xff0c;拥有卓越的性能和丰富的功能。采用全新轻量化的界面UI&#xff0c;让您可以更加方便快捷地解决 知识付费和运营赞助的难题。同时&#xff0c;它基于高性能的Thin…

ubuntu安装docker的详细教程

检查卸载老版本docker ubuntu下自带了docker的库&#xff0c;不需要添加新的源。 但是ubuntu自带的docker版本太低&#xff0c;需要先卸载旧的再安装新的。 注&#xff1a;docker的旧版本不一定被称为docker&#xff0c;docker.io 或 docker-engine也有可能&#xff0c;所以卸…

Hypermesh碰撞安全之头部撞击模拟

1、首先到自定义工作面板中选择Engineering Solutions(工程解决方案&#xff09; 2、进入行人保护建模流程模块 3、导入所需要的模型 4、对模型进行切割&#xff0c;选择所需要保留的区域 5、单击next进入下一界面 6、选择打击类型 下一步进入&#xff1a; 这样就完成了打击点…

基于深度学习的唇语识别系统的设计与实现

概要 人工智能作为三大工程之一&#xff0c;从上个世纪至今仍然活跃于各个行业的研究与应用之中&#xff0c;应时代的热潮方向&#xff0c;本 课题主要针对深度学习技术应用于唇语识别当中&#xff0c;实现词语唇语的翻译功能。唇语识别在图像处理中一直是一个富 有挑战性的课题…

基础知识学习 -- qnx 系统

QNX是一个基于优先级抢占的系统。 这也导致其基本调度算法相对比较简单。因为不需要像别的通用操作系统考虑一些复杂的“公平性”&#xff0c;只需要保证“优先级最高的线程最优先得到 CPU”就可以了。 基本调度算法 调度算法&#xff0c;是基于优先级的。QNX的线程优先级&a…

【LabVIEW FPGA入门】单周期定时循环

单周期定时循环详解 单周期定时环路是FPGA编程中最强大的结构之一。单周期定时循环中的代码更加优化&#xff0c;在FPGA上占用更少的空间&#xff0c;并且比标准While循环中的相同代码执行得更快。单周期定时环路将使能链从环路中移除&#xff0c;以节省FPGA上的空间。…