【蓝桥集训】第七天——并查集

news2025/8/2 8:23:40

作者:指针不指南吗
专栏:Acwing 蓝桥集训每日一题

🐾或许会很慢,但是不可以停下来🐾

文章目录

  • 1.亲戚
  • 2.合并集合
  • 3.连通块中点的数量

有关并查集的知识学习可以移步至—— 【算法】——并查集

1.亲戚

或许你并不知道,你的某个朋友是你的亲戚。

他可能是你的曾祖父的外公的女婿的外甥女的表姐的孙子。

如果能得到完整的家谱,判断两个人是否是亲戚应该是可行的,但如果两个人的最近公共祖先与他们相隔好几代,使得家谱十分庞大,那么检验亲戚关系实非人力所能及。

在这种情况下,最好的帮手就是计算机。

为了将问题简化,你将得到一些亲戚关系的信息,如Marry和Tom是亲戚,Tom和Ben是亲戚,等等。

从这些信息中,你可以推出Marry和Ben是亲戚。

请写一个程序,对于我们的关于亲戚关系的提问,以最快的速度给出答案。

输入格式

输入由两部分组成。

第一部分以 N,M开始。N 为问题涉及的人的个数。这些人的编号为 1,2,3,…,N。下面有 M 行,每行有两个数 a i , b i a_i,b_i ai,bi ,表示已知 a i a_i ai b i b_i bi 是亲戚。

第二部分以 Q 开始。以下 Q 行有 Q 个询问,每行为 c i , d i c_i,d_i ci,di ,表示询问 c i c_i ci d i d_i di 是否为亲戚。

输出格式

对于每个询问 c i , d i c_i,d_i ci,di ,输出一行:若 c i c_i ci d i d_i di 为亲戚,则输出“Yes”,否则输出“No”。

数据范围

1≤N≤20000,
1≤M≤ 1 0 6 10^6 106 ,
1≤Q≤ 1 0 6 10^6 106 .

输入样例:

10 7
2 4
5 7
1 3
8 9
1 2
5 6
2 3
3
3 4
7 10
8 9

输出样例:

Yes
No
Yes
  • 思路

    • 把每个家族看成一个集合:人之间互为亲戚,则说明他们是一个家族的,用一个编号来表示;
    • 这个题比较简单,就是并查集的两个朴素操作:
      1. 两个人互为亲戚,进行家族合并,即并查集合并
      2. 查询两个人是否为亲戚,即看看这两人的家族是否一样
  • 代码实现

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=200010;
    
    int n,m;   //n表示人数,m表示操作的次数
    int p[N];
    
    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--){   //m次合并操作,亲戚互认
            int a,b;
        	scanf("%d%d",&a,&b);
            if(find(a)!=find(b))  p[find(a)]=find(b);   //家族集合合并
        }
        
        int q;
        cin>>q;
        while(q--){  //q次查询,是否是亲戚,一个家族集合的
            int x,y;
            scanf("%d%d",&x,&y);
            if(find(x)==find(y))  puts("Yes");   
            else puts("No");
        }
        
        
        return 0;
    }
    

2.合并集合

一共有 n 个数,编号是 1∼n,最开始每个数各自在一个集合中。

现在要进行 m 个操作,操作共有两种:

  1. M a b,将编号为 a 和 b 的两个数所在的集合合并,如果两个数已经在同一个集合中,则忽略这个操作;
  2. Q a b,询问编号为 a 和 b 的两个数是否在同一个集合中;

输入格式

第一行输入整数 n 和 m。

接下来 m 行,每行包含一个操作指令,指令为 M a bQ a b 中的一种。

输出格式

对于每个询问指令 Q a b,都要输出一个结果,如果 a 和 b 在同一集合内,则输出 Yes,否则输出 No

每个结果占一行。

数据范围

1≤n,m≤ 1 0 5 10^5 105

输入样例:

4 5
M 1 2
M 3 4
Q 1 2
Q 1 3
Q 3 4

输出样例:

Yes
No
Yes
  • 代码实现

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=100010;
    
    int n,m; //n表示点的数量,m表示操作的次数
    int p[N];  //存的每个节点的父节点
    
    int find(int x) //返回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; //最开始,每个点都各自在一个集合中,so父节点就是他本身;
        
        while(m--){
         
         char op[2];
         int a,b;
         scanf("%s%d %d",op,&a,&b);
         
         //合并
         if(op[0]=='M') p[find(a)]=p[find(b)];  //让a的祖宗节点等于b的祖宗节点,让a的祖宗节点直接插在b祖宗节点下面
         else{
             if(find(a)==find(b)) puts("Yes");  //判断是否属于同一个集合
             else puts("No");
         }  
        }
        
        return 0;
    }
    

注意

读入字母M或者是Q的时候,使用字符串op[2],是因为直接用char的话,可能会出现空格换行的问题作物,这种比较保险,记得在后面使用的时候,用op[0],不能直接使用op

puts自动包含换行

3.连通块中点的数量

给定一个包含 n 个点(编号为 1∼n)的无向图,初始时图中没有边。

现在要进行 m 个操作,操作共有三种:

  1. C a b,在点 a 和点 b 之间连一条边,a 和 b 可能相等;
  2. Q1 a b,询问点 a 和点 b 是否在同一个连通块中,a 和 b 可能相等;
  3. Q2 a,询问点 a 所在连通块中点的数量;

输入格式

第一行输入整数 n 和 m。

接下来 m 行,每行包含一个操作指令,指令为 C a bQ1 a bQ2 a 中的一种。

输出格式

对于每个询问指令 Q1 a b,如果 a 和 b 在同一个连通块中,则输出 Yes,否则输出 No

对于每个询问指令 Q2 a,输出一个整数表示点 a 所在连通块中点的数量

每个结果占一行。

数据范围

1≤n,m≤ 1 0 5 10^5 105

输入样例:

5 5
C 1 2
Q1 1 2
Q2 1
C 2 5
Q2 5

输出样例:

Yes
2
3
  • 思路

    • 连通块就是一个点的集合:集合中的点可以相互到达,直接或者是间接都是可以的;

    • 这时候我们可以把它类比成一个树,运用并查集,一个点集合,我们可以用一个编号来表示,属于同一个编号,就说明两个点之间可以相互到达,在一个连通块里面;

    • 有三个操作:

      1. 两点之间连一条边,那么这两个点所在集合中的点,都是可以相互到达的,即合成一个连通块,用并查集中的合并操作;

      2. 判断是否在一个连通块,用并查集的查询;

      3. 询问一个点集合的数量,需要我们额外维护,初始化的时候每个集合1个,合并的时候,两个集合数量相加,最后输出即可

  • 代码实现

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int N=1000010;
    int n,m;
    int p[N],sizel[N];  //p表示父节点,sizel表示集合的大小,记住sizel里面放的是祖宗节点,后面容易出错
    
    int find(int n)  //返回祖宗节点
    {
        if(p[n]!=n) p[n]=find(p[n]);
        return p[n];
    }
    
    
    int main()
    {
        scanf("%d%d",&n,&m);  //读入点的数量和操作的次数
        
        for(int i=1;i<=n;i++){   //初始化,父节点就是它本身;集合大小都是1,只有他自己
            p[i]=i;
            sizel[i]=1;
        }
        
        char op[5];   
        while(m--){
            scanf("%s",op);  //读入操作的名字
            
            if(op[0]=='C'){   //合并
            int a,b;
            scanf("%d%d",&a,&b);
            if(find(a)==find(b)) continue;  //相同则进入下个循环
            else{   //不同即操作,两步的顺序不能反!!!
                sizel[find(b)]+=sizel[find(a)];  //b的集合大小加上a的集合大小
                p[find(a)]=find(b);   //让a的祖宗节点指向b的祖宗节点
            }
         }
         
            else if(op[1]=='1'){  //查询是否一个集合
                int a,b;
                scanf("%d%d",&a,&b);
                if(find(a)==find(b))  puts("Yes");
                else puts("No");
            }
            
            else{
                if(op[1]=='2') {   //输出集合大小
                    int d;
                    scanf("%d",&d);
                    printf("%d\n",sizel[find(d)]);  
                }
            }
        }
        
        return 0;
    }
    

Alt

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为OD机试题,用 Java 解【喊 7 的次数重排】问题

最近更新的博客 华为OD机试 - 猴子爬山 | 机试题算法思路 【2023】华为OD机试 - 分糖果(Java) | 机试题算法思路 【2023】华为OD机试 - 非严格递增连续数字序列 | 机试题算法思路 【2023】华为OD机试 - 消消乐游戏(Java) | 机试题算法思路 【2023】华为OD机试 - 组成最大数…

大数据开发 - Java入门2

目录Java基础知识注释关键字常量标识符测试题回顾Java基础知识 注释 对程序的解释说明 分类&#xff1a; 单行注释&#xff1a;// 对本行后面的内容进行注释多行注释&#xff1a;/*解释内容 */文档注释 &#xff1a;/** 注释内容*/ --用于产生帮助文档&#xff0c;也有多行注…

高通平台开发系列讲解(SIM卡篇)SIM卡基础概念

文章目录 一、SIM卡基本定义二、卡的类型三、SIM卡的作用三、SIM卡基本硬件结构四、SIM卡的内部物理单元五、卡文件系统沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇文章将介绍SIM的相关组件。 一、SIM卡基本定义 SIM卡是一种智能卡(ICC Card/UICC Card) SIM…

在线客服系统接入网站会员,绑定会员ID,展示会员昵称头像,传递手机号等扩展字段【唯一客服】...

在客服系统聊天链接里&#xff0c;可以带上自己网站的会员信息&#xff0c;例如&#xff1a;昵称、头像、手机号等 具体使用方式如下 聊天链接中增加以下参数&#xff1a; visitor_id: 自有会员visitor_name: 自有会员名称avator: 自有会员头像lang: 多语言 cn 中文 &#xff0…

链接服务器查询导致的阻塞

背景客户反馈数据库在上午10点时出现严重阻塞&#xff0c;阻塞源头会话在等待OLEDB&#xff0c;没有见过这个等待类型&#xff0c;请我们协助分析。现象登录SQL专家云&#xff0c;进入趋势分析&#xff0c;下钻到10点钟的活动会话&#xff0c;看到发生了两次严重的阻塞。转到活…

指针的进阶【上篇】

文章目录&#x1f4c0;1.字符指针&#x1f4c0;2.指针数组&#x1f4c0;3.数组指针&#x1f4bf;3.1.数组指针的定义&#x1f4bf;3.2. &数组名VS数组名&#x1f4bf;3.3.数组指针的使用&#x1f4c0;1.字符指针 int main() {char ch w;char* pc &ch;// pc就是字符指…

数据结构之顺序表篇

一、顺序表概念 二、顺序表各类接口实现 *顺序表初始化 **顺序表销毁 ***顺序表插入操作 ****顺序表删除操作 *****顺序表查找操作 ******顺序表实现打印操作 三、顺序表整体实现源码 *SeqList.h **SeqList.c ***test.c 一、顺序表概念 讲顺序表之前先引入线性表概念&#xff…

可视化服务编排在金融APP中的实践

本文重点介绍了京东金融APP在BFF层实践过程中遇到的问题&#xff0c;并引出可视化服务编排在金融APP中的落地实践&#xff0c;其中重点介绍了可视化服务编排系统的核心功能及实现。 可视化服务编排系统已经稳定支持了金融APP从去年618到现在的所有发版迭代&#xff0c;对人效提…

Apache ActiveMQ安装和使用

文章目录Apache ActiveMQ安装和使用 环境下载安装配置启动登录Apache ActiveMQ安装和使用 环境 Ubuntu20.04 下载 官网&#xff1a;https://activemq.apache.org/download-archives 如下载5.14.4版本&#xff0c;apache-activemq-5.14.4-bin.tar.gz&#xff0c;测试过没问题…

分布式算法 - 一致性Hash算法

一致性Hash算法是个经典算法&#xff0c;Hash环的引入是为解决单调性(Monotonicity) 的问题&#xff1b;虚拟节点的引入是为了解决 平衡性(Balance) 问题。一致性Hash算法引入在分布式集群中&#xff0c;对机器的添加删除&#xff0c;或者机器故障后自动脱离集群这些操作是分布…

MySQL索引类型及原理?一文读懂

一、什么是MySQL索引&#xff1f; MySQL索引是一种数据结构&#xff0c;用于提高数据库查询的性能。它类似于一本书的目录&#xff0c;通过在表中存储指向数据行的引用&#xff0c;使得查询数据的速度更快。 在MySQL中&#xff0c;索引通常是在表上定义的&#xff0c;它们可以…

本地新创建的项目,关联/上传到码云

以下示例以mac为例&#xff0c;window将相关步骤改为windows对应的操作即可1、打开终端&#xff0c;通过终端命令 cd 切换到新建的本地项目目录下&#xff0c;如&#xff1a;&#xff08;/Users/wangcongming/Documents/TuoTuo/mobile_acitvity 为我的新建项目地址&#xff09;…

使用 ChatGPT ,通过自然语言编写 eBPF 程序和追踪 Linux 系统

eBPF 是一项革命性的技术&#xff0c;起源于 Linux 内核&#xff0c;可以在操作系统的内核中运行沙盒程序。它被用来安全和有效地扩展内核的功能&#xff0c;而不需要改变内核的源代码或加载内核模块。今天&#xff0c;eBPF被广泛用于各类场景&#xff1a;在现代数据中心和云原…

「RISC-V Arch」SBI 规范解读

术语 SBI&#xff0c;Supervisor Binary Interface&#xff0c;管理二进制接口 U-Mode&#xff0c;User mode&#xff0c;用户模式 S-Mode&#xff0c;Supervisor mode&#xff0c;监督模式 VS-Mode&#xff0c;Virtualization Supervisor mode&#xff0c;虚拟机监督模式 …

嵌入式 Linux Shell编程

目录 1、shell脚本 2、执行shell脚本 3、shell脚本编写 3.1 shell变量 3.2 标准变量或环境变量 3.4 变量赋值有五种格式 3.5 运算符和表达式 关系运算符 布尔运算符 3.6 Test命令用法 1、判断表达式 2、判断字符串 3.判断整数 4、判断文件 3.7 数组 1、数组定义…

什么是 RPA ?What is robotic process automation (RPA)?

目录 前言 What is a business process? 什么是业务流程? What does "robotic process automation" mean?“机器人过程自动化”是什么意思? What is robotic process automation (RPA)?什么是机器人流程自动化 (RPA)? What

SGI 空间配置器

前言 空间配置器是 STL 六大组件之一&#xff0c;它总是隐藏在容器的背后&#xff0c;默默工作&#xff0c;默默付出。本文为《STL 源码剖析》读书笔记&#xff0c;主要讨论 SGI 版本空间的配置和释放&#xff0c;对代码进行解读时会改变一些写法&#xff0c;使其更易于阅读。…

__stack_chk_fail问题分析

一、问题进程收到SIGABRT信号异常退出&#xff0c;异常调用栈显示__stack_chk_fail*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** Build fingerprint: Pico/A7H10/PICOA7H10:10/5.5.0/smartcm.1676912090:userdebug/dev-keys Revision: 0 ABI: arm64 Times…

VS Code下载安装教程

VS Code下载安装使用教程 目录VS Code下载安装使用教程一、下载二、安装三、使用教程3.1 VS Code中的第一个页面HelloWorld.html3.2 VS Code插件安装3.2.1 安装中文界面3.2.3 安装 Open in Browser插件3.2.4 安装Auto Rename Tag插件注意&#xff1a;3.3 code .命令&#xff0c…

EasyNLP集成K-Global Pointer算法,支持中文信息抽取

作者&#xff1a;周纪咏、汪诚愚、严俊冰、黄俊 导读 信息抽取的三大任务是命名实体识别、关系抽取、事件抽取。命名实体识别是指识别文本中具有特定意义的实体&#xff0c;包括人名、地名、机构名、专有名词等&#xff1b;关系抽取是指识别文本中实体之间的关系&#xff1b;…