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

news/2024/4/20 17:03:44/文章来源:https://blog.csdn.net/qq_73659829/article/details/129198172

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

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

文章目录

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

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

1.亲戚

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

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

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

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

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

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

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

输入格式

输入由两部分组成。

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

第二部分以 Q 开始。以下 Q 行有 Q 个询问,每行为 ci,dic_i,d_ici,di ,表示询问 cic_icidid_idi 是否为亲戚。

输出格式

对于每个询问ci,dic_i,d_ici,di ,输出一行:若 cic_icidid_idi 为亲戚,则输出“Yes”,否则输出“No”。

数据范围

1≤N≤20000,
1≤M≤10610^6106 ,
1≤Q≤10610^6106 .

输入样例:

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≤10510^5105

输入样例:

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≤10510^5105

输入样例:

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.luyixian.cn/news_show_74416.aspx

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

相关文章

c语言tips-大端小端存储介绍和使用union判断大小端

1. 大小端介绍 大端&#xff08;Big Endian&#xff09;和小端&#xff08;Little Endian&#xff09;是两种CPU或者计算机系统存储数据的方式。 在大端系统中&#xff0c;数据的高位字节&#xff08;MSB&#xff09;存储在内存地址的低位&#xff0c;低位字节&#xff08;LSB…

【C++】C++入门(下)

引用 什么是引用&#xff1f;   引用是给一个已经存在的变量取一个别名&#xff0c;在语法上并不会给这个别名开一个空间&#xff0c;它和她引用的变量共用一个空间。但是实际上引用也是开了一块空间的&#xff0c;用来存放引用名。引用是按照指针的方式来实现的。引用语法&…

《分布式技术原理与算法解析》学习笔记Day23

分布式数据复制 我们在进行分布式数据存储设计时&#xff0c;通常会考虑对数据进行备份&#xff0c;以提高数据的可用性和可靠性&#xff0c;“数据复制技术”就是实现数据备份的关键技术。 什么是数据复制技术&#xff1f; 在分布式数据库系统中&#xff0c;通常会设置主备…

华为OD机试用Python实现 -【统一限载货物数最小值】(2023-Q1 新题)

华为OD机试题 华为OD机试300题大纲统一限载货物数最小值题目描述输入描述输出描述说明示例一输入输出说明示例二输入输出说明Python 代码实现算法逻辑华为OD机试300题大纲 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查…

python爬虫常见错误

python爬虫常见错误前言python常见错误1. AttributeError: WebDriver object has no attribute find_element_by_id1. 问题描述2. 解决办法2. selenium&#xff1a;DeprecationWarning: executable_path has been deprecated, please pass in1. 问题描述2. 解决办法3. 下载了包…

k8s-资源限制-探针检查

文章目录一、资源限制1、资源限制的使用2、reuqest资源&#xff08;请求&#xff09;和limit资源&#xff08;约束&#xff09;3、Pod和容器的资源请求和限制4、官方文档示例5、资源限制实操5.1 编写yaml资源配置清单5.2 释放内存&#xff08;node节点&#xff0c;以node01为例…

《程序员思维修炼》速读笔记

文章目录书籍信息概览绪论从新手到专家的历程认识大脑利用右脑调试大脑主动学习积累经验控制注意力超越专家图解书籍信息 书名&#xff1a;《程序员思维修炼&#xff08;修订版&#xff09;》 作者&#xff1a;[美] Andy Hunt 概览 绪论 再提“实用”关注情境所有人都关注这…

Flutter3引用原生播放器-IOS(Swift)篇

前言由于Flutter项目中需要使用到播放器功能&#xff0c;因此对flutter中各种播放器解决方案进行了一番研究和比对&#xff0c;最后决定还是自己通过Plugin的方法去引用原生播放器符合自己的需求&#xff0c;本篇文章会对各种解决方案做一个简单的比较&#xff0c;以及讲解一下…

线材-电子线载流能力

今天来讲的是关于电子线的一个小知识&#xff0c;可能只做板子的工程师遇到此方面的问题会比较少&#xff0c;做整机的工程师则必然会遇到此方面问题&#xff0c;那就是线材问题。 下面主要说下电子线的过电流能力。&#xff08;文末有工具下载&#xff09;电子线&#xff08;h…

[11]云计算|简答题|案例分析|云交付|云部署|负载均衡器|时间戳

升级学校云系统我们学校要根据目前学生互联网在线学习、教师教学资源电子化、教学评价过程化精细化的需求&#xff0c;计划升级为云教学系统。请同学们根据学校发展实际考虑云交付模型包含哪些&#xff1f;云部署采用什么模型最合适&#xff1f;请具体说明。9月3日买电脑还是租…

@Value注解的使用(可用于配置文件)

基本概念Value&#xff1a;注入配置文件中的内容。只要是spring的注解类&#xff08;service,compotent, dao等&#xff09;中都可以。Component&#xff1a;泛指组件&#xff0c;当组件不好归类的时候&#xff0c;可以使用这个注解进行标注。AutoWired&#xff1a;自动导入依赖…

Jinja2----------模板渲染、模板访问对象属性

目录 1.Jinja2 1.简介 2.Jinja2模板 2.模板渲染 app.py templates/index.html templates/blog_detail.html 效果 3.模板访问对象属性 app.py templates/index.html 效果 1.Jinja2 1.简介 Jinja2是Python下一个被广泛应用的模版引擎&#xff0c;他的设计思想来…

二叉树的前序遍历-java两种方式-力扣144

一、题目描述给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。示例 1&#xff1a;输入&#xff1a;root [1,null,2,3]输出&#xff1a;[1,2,3]示例 2&#xff1a;输入&#xff1a;root []输出&#xff1a;[]示例 3&#xff1a;输入&#xff1a;root [1]输出…

【Linux驱动开发100问】什么是模块?如何编写和使用模块?

&#x1f947;今日学习目标&#xff1a;什么是Linux内核&#xff1f; &#x1f935;‍♂️ 创作者&#xff1a;JamesBin ⏰预计时间&#xff1a;10分钟 &#x1f389;个人主页&#xff1a;嵌入式悦翔园个人主页 &#x1f341;专栏介绍&#xff1a;Linux驱动开发100问 什么是模块…

分布式之PBFT算法

写在前面 在分布式之拜占庭问题 一文中我们分析了拜占庭问题&#xff0c;并一起看了支持拜占庭容错的口信消息性和签名消息性算法&#xff0c;但是这两种算法都有一个非常严重的问题&#xff0c;就是消息数量太多&#xff0c;通信的成本太大&#xff0c;消息数量复杂度为O(n ^…

HMM(隐马尔科夫模型)-理论补充2

目录 一.大数定理 二.监督学习方法 1.初始概率 2.转移概率 3.观测概率 三.Baum-Welch算法 1.EM算法整体框架 2. Baum-Welch算法 3.EM过程 4.极大化 5.初始状态概率 6.转移概率和观测概率 四.预测算法 1.预测的近似算法 2.Viterbi算法 1.定义 2. 递推&#xff1…

2023安装archlinux笔记

本文只是个笔记&#xff0c;不是详细教程&#xff0c;仅供参考。 安装过程基本与 《2021年vmware安装archlinux》 https://blog.csdn.net/lxyoucan/article/details/115226297 差不多。 无U盘安装 不想格式化U盘了&#xff0c;直接从硬盘安装。参考一下文章。 《没有U盘纯硬…

Laravel框架02:路由与控制器

Laravel框架02&#xff1a;路由与控制器一、路由配置文件二、路由参数三、路由别名四、路由群组五、控制器概述六、控制器路由七、接收用户输入一、路由配置文件 以web网页路由文件为例&#xff1a; 默认根路由 路由定义格式Route::请求方式(请求的URL, 匿名函数或控制响应的方…

CV学习笔记-MobileNet

MobileNet 文章目录MobileNet1. MobileNet概述2. 深度可分离卷积&#xff08;depthwise separable convolution&#xff09;2.1 深度可分离卷积通俗理解2.2 深度可分离卷积对于参数的优化3. MobileNet网络结构4. 代码实现4.1 卷积块4.2 深度可分离卷积块4.3 MobileNet定义4.4 完…

一步步教你电脑变成服务器,tomcat的花生壳设置(原创)

1&#xff0c;首先你去https://console.oray.com/这网站注册个帐号&#xff0c;如果注册成功它会送你一个免费域名&#xff0c;当然不记得也没关系&#xff0c;你记住你注册的 帐号跟密码&#xff0c;然后下载它的软件&#xff08;花生壳动态域名6.0正式版&#xff09;有xp跟li…