【第十四课】并查集(acwing-836合并集合 / 做题思路 /c++代码)

news2024/12/28 5:48:00

目录

错误思路(但能骗分emm)--邻接矩阵(可以跳过)

思路

存在的问题

代码如下

并查集

思路

代码如下

 一些解释


错误思路(但能骗分emm)--邻接矩阵(可以跳过)

思路

刚看到这道题我自己做的时候,因为之前学的trie树的时候意识到使用二维数组的含义,所以在思考这道题的时候也更偏向于使用二维数组。

于是经过不断试错,就想出来了个这种做法:原理就是--图中的邻接矩阵把输入的两个集合编号当作二维数组的下标,执行过M操作的两个集合编号对应的下标会更改为1,"代表"这两个集合合并了,为满足题意我们使用if语句,当两个集合已经执行过"合并"操作,就break。对于Q操作,我们直接判断输入的两个集合编号在二维矩阵中对应的数是否是1就ok了

这样我们表面上能够实现部分"合并"操作某些情况下输入输出是符合题意且正确的

存在的问题

然而这种方法

第一:他其实并没有真正的完成M合并操作,与题意并不相符。

第二:由于我们创建了二维数组,题目要求n的数据范围最大是1e5,我们知道二维矩阵创建应该是n*n的,首先要创建一个1e5*1e5的二维数组本来在大部分计算机上就实现不了,超过了系统可用的内存量;其次我们数组元素是整型int,在32位系统中,其最大索引2.1×10^9,而二维数组元素最多有10^10,从这方面来讲也是不可行的( 在64位系统中,最多可有9.2*10^18,不存在该问题)。

于是我们只能缩小N的取值为1e3,这就已经减少了很多答案。

其实关于邻接矩阵创建二维数组的问题在图的学习中我们已经说过,由于二维数组使用到的坐标可能很少,空间浪费比较严重,我们当时就提出了邻接表的写法。我这里懒得折腾了,就没再思考那一种写法了(doge)。 

数组内存大小限制的因素: 

第三:关于用这种方法得到错误结果的例子:

如果我们执行下面三个操作

M 1 2
M 2 3
Q 1 3

按照我们上面的思路:输出结果会是No。但其实我们首先将1和2合并到同一个集合中,然后将2和3合并到同一个集合中。1、2和3应该都在同一个集合中。

对于第三个原因,在后面使用并查集的代码进行操作时其实结果也是No,因此暂不深入讨论该因素。

因此这种方法是错误的。

代码如下

这里给出按照这种思路能够正确执行的代码 

#include<iostream>
#include<cstring>//引头文件
using namespace std;
const int N=1e3+10;
int p[N],s[N][N],n,m;

int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        p[i]=i;
    }
    char op[2];
    while(m--)
    {
        scanf("%s",op);
        int a=0,b=0;
        if(strcmp(op,"M")==0)//对于字符串的比较要用到strcmp函数
        {
            cin>>a>>b;
            if(s[a][b]==1)break;
            else s[a][b]=1;
        }
        else if(strcmp(op,"Q")==0){
            cin>>a>>b;
            bool ans=s[a][b];
            if(ans==1)printf("Yes\n");
            else printf("No\n");
        }
    }
    return 0;
}

关于这种方法的正确率什么的我也不是很清楚,只当一种下下策把。 

并查集

其实刚看到这道题,我对这道题题意有一些困惑:合并集合之后的两个集合何去何从了呢?最后他们是都放进了a还是b里呢?另一个集合里面难道是空了么?如果合并之后只会留下一个集合,那么留下两个中的某一个有什么影响呢?还有如果这两个集合里有重复元素怎么办呢?不需要考虑么?

感觉我在题意理解上真是,,,哎

下面是bing的一些解释

思路

我们先明确要实现的两个操作:M 合并两个集合 Q 查询两个集合是否已经合并

我们先想复杂的做法(我甚至这个都没想到😂):怎么实现Q?判断这两个元素是不是在同一个集合里p[x]==p[y],用一个数组p来表示每个元素所属的集合;怎么实现M呢?把其中一个集合里面的所有元素的所属集合也就是p数组的值都更改为另一个数组

Q操作还好,M操作简直是太麻烦了,集合里万一有好多元素呢?怎么一个一个改?

于是我们就想到并查集这种算法:我们用树来表示每个集合,树根的编号就是集合编号。每个节点的元素都存储他的父节点,这个节点的下标代表这个元素本身。

利用这种方式来实现我们的M和Q操作:M操作就是利用while循环找到两个元素所在树的树根 (判断方式是p[x]==x,我们规定根节点的父节点为其自己),然后将其中一个的p[x]指向另一个元素的父节点即可,也就是直接把这个集合这棵树直接连到另一棵树上

关于其中找父节点的过程可以进行优化:当我们找到了一个节点的根节点,那么从根节点到该元素路径上的所有节点的p[x]都应赋值为根节点x,这样就避免了多次重复查找根节点。这也就是我们常说的路径压缩

代码如下

#include<iostream>
using namespace std;
const int N=1e5+10;
int n,m;
int p[N];
int find(int x)
{
    if(p[x]!=x)p[x]=find(p[x]);//路径压缩
    return p[x];//返回根节点 也就是集合编号
}
int main()
{
    cin>>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))printf("Yes\n");
            else printf("No\n");
        }
    }
}

 一些解释

1.op的 if 比较

在上面邻接矩阵的方法里我直接让op这一整个字符数组(即字符串)都与字母进行比较

strcmp(op,"M")==0

注意字符串的比较只能用strcmp函数,不可以直接用== 。补充strcmp函数两个字符串相等返回0,前者小于后者,返回<0的数..。

而在这里,我们直接将op数组第一个元素也就是op[0]与一个字符进行比较,这里就可以直接使用==啦

这个之前好像遇到过很多次了,要记住!

2.puts函数输出

在这里我用了printf函数进行输出,需要写的很多。但是puts函数就可以直接简化书写

if(find(a)==find(b))puts("Yes");
    else puts("No");

这是因为 puts 会自动将换行符 ('\n') 附加到输出中,可以使代码更简洁,并减少忘记包含换行符的机会。简化语法书写。

3.递归函数find

由于我们的优化是,寻找其中一个节点的根节点,那么每次都会不断地向上搜索,而这中间搜索到的节点,也就是从根节点到该元素路径上的所有节点其根节点都是该元素的根节点,都直接赋值为最终的结果。也就达到了优化效果。

如果并未找到根节点(递归出口),就不断执行p[x]=find(p[x]) (递归内容)。还记得递归函数的这两个要素吧~

4.关于传递性

关于这个样例,,,也试了其他博主的博客的代码,执行结果还是No,我也不是很确定关于其传递性的说法了,欢迎指点!!

4 3
M 1 2
M 2 3
Q 1 3
No

好啦并查集就先写到这里,有问题欢迎指出!

期末周也过去了,就好好学算法吧。这几天会先玩一下[😂]希望回来之后是每天日更!!

一起加油!!

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

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

相关文章

如何配置Pycharm服务器并结合内网穿透工具实现远程开发

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《Linux》《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;…

开启C++之旅(下):引用、内联函数及现代特性(auto和范围for循环)

上次介绍了&#xff1a;开启C之旅&#xff08;上&#xff09;&#xff1a;探索命名空间与函数特性&#xff08;缺省参数和函数重载&#xff09; 今天就接着进行c入门的知识讲解 文章目录 1.引用1.1引用概念1.2引用特性1.3常引用其他情况 1.4引用使用场景1.4.1做参数1.4.2做返回…

使用VSCode内的jupyter编写R语言:绘制中国省份地区热力图

R语言绘制中国省份地区热力图教程 1、R语言的安装和编辑器的选择 对于一门从未接触过的编程语言&#xff0c;相信大家的吐槽点和我一样&#xff1a;又要安装软件&#xff0c;配置环境&#xff01;其实R语言的安装和环境配置并不复杂&#xff0c;只需要安装两部分内容&#xf…

第15届蓝桥STEMA测评真题剖析-2023年12月17日Scratch编程初中级组

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第166讲。 第15届蓝桥第3次STEMA测评&#xff0c;这是2023年12月17日举办的STEMA&#xff0c;比赛仍然采取线上形式。这…

ESP32-Touch(Arduino)

Touch Touch传感器是一种外围设备&#xff0c;具有内部振荡器电路&#xff0c;可在固定时间段内测量相应GPIO引脚上的充电/放电频率。 因此&#xff0c;这些触摸传感器也被称为电容式传感器。例如&#xff0c;如果您触摸这些引脚中的任何一个&#xff0c;手指电荷将改变这个周…

Vue学习计划-Vue3--核心语法(十)Proxy响应式原理

Proxy响应式原理 1.Vue2的响应式 实现原理&#xff1a; 对象类型&#xff1a;通过Object.defineProperty()对属性的读取、修改进行拦截&#xff08;数据劫持&#xff09;数组类型&#xff1a;通过重写更新数组的一系列方法来实现拦截&#xff0c;&#xff08;对数组的变更方法…

【数学建模】图论模型

文章目录 图的基础理论及networkx简介图的基本概念图的表示及Networkx简介图的表示NetworkX简介 最短路算法及其Python实现固定起点到其余各点的最短路算法每对顶点间的最短路算法最短路应用 最小生成树算法及其networkx实现基本概念最小生成树算法最小生成树应用 匹配问题最大…

【JavaEE进阶】 利用Spring简单实现加法计算器和用户登录

文章目录 &#x1f38d;序言&#x1f333;加法计算器&#x1f6a9;准备工作&#x1f6a9;约定前后端交互接⼝&#x1f332;后端服务器代码的书写 &#x1f334;用户登录&#x1f6a9;效果展示&#x1f6a9;准备工作&#x1f6a9;约定前后端交互接⼝&#x1f388;需求分析&#…

【leetcode刷题】模拟专题

模拟 一、替换所有的问号1、题目链接2、解析3、代码 二、提莫攻击1、题目链接2、解析3、代码 三、Z字形变换1、题目链接2、解析3、代码 四、外观数列1、题目链接2、解析3、代码 五、数青蛙1、题目链接2、解析3、代码 一、替换所有的问号 1、题目链接 leetcode链接 2、解析 3、…

【排序算法】一、排序概念和直接插入排序(C/C++)

「前言」文章内容是排序算法之直接插入排序的讲解。&#xff08;所有文章已经分类好&#xff0c;放心食用&#xff09; 「归属专栏」排序算法 「主页链接」个人主页 「笔者」枫叶先生(fy) 目录 一、排序概念的介绍二、直接插入排序2.1 原理2.2 代码实现&#xff08;C/C&#xf…

鸿蒙开发-UI-布局-层叠布局

鸿蒙开发-UI-布局 鸿蒙开发-UI-布局-线性布局 文章目录 前言 一、基本概念 二、对齐方式 三、Z序控制 四、使用场景 总结 前言 上文详细学习了线性布局&#xff0c;学习了线性容器内子元素在主轴以及交叉轴上的排列方式&#xff0c;子元素自适应相关的知识点&#xff0c;本文继…

墙地砖外形检测的技术方案-图像形态学

基础理论 得到的灰度图像需进行二值化处理和区域填充&#xff0c;涉及两个步骤&#xff0c;第一&#xff0c;对图像进行分割&#xff0c;将图像分割成目标和背景&#xff1b; 第二&#xff0c;对分割后图像进行区域填充。本例中的背景为黑色&#xff0c;可以通过基本的全局阈…

智能管理护航制造企业安全生产:信息化升级解决方案解析-亿发

安全生产信息化是通过充分利用信息技术&#xff0c;及时采集安全生产管理中的各种要素和数据&#xff0c;并进行统计分析&#xff0c;随后将分析结果及时反馈&#xff0c;以实现对安全生产管理的指导和帮助&#xff0c;旨在提高安全生产管理的效能。 在提升安全生产管理水平方…

重磅!ESI高被引论文阈值发布

1月11日&#xff0c;科睿唯安&#xff08;Clarivate Analytics&#xff09;公布了最新的ESI数据。 注&#xff1a;ESI的更新时间为每奇数月的第二个星期四。 Essential Science Indicators (ESI) 是一种分析工具&#xff0c;可帮助识别 Web of Science 核心合集中表现最好的研…

浙江科聪完成A轮近亿元融资:持续领跑移动机器人控制系统市场

近日&#xff0c;中国移动机器人控制系统行业领军企业浙江科聪完成A轮近亿元融资&#xff0c;本轮融资由元璟资本投资。硬核资本加持硬核科技&#xff0c;本轮资金将主要用于加大研发投入&#xff0c;加速产品迭代和提升服务质量&#xff0c;加强公司全球营销网络的建设。 移动…

抖音弹幕直播玩法汉字找不同文字找不同无人值执守自动玩游戏自带语音播报的开发日志

#找不同# 要解决如下几个问题&#xff1a; 1.声音sprite的录制和调用&#xff0c;解决方案以及解决库如下&#xff1a; howler.min.js://一款不错的音频播放js库。 2.鼠标自动飘浮,使用的库 anime.min.js 3.资源预加载 preload.min.js 4.其它使用到的库 jquery,vue

自动化测试:fixture学得好,Pytest测试框架用到老

在pytest中&#xff0c;fixture是一种非常有用的特性&#xff0c;它允许我们在测试函数中注入数据或状态&#xff0c;以便进行测试。而参数化则是fixture的一个特性&#xff0c;它允许我们将不同的数据传递给fixture&#xff0c;从而进行多次测试。 本文将介绍如何在pytest中使…

【前端框架】Vue3合集

一、Vue3初识 1、create-vue create-vue是Vue官方新的脚手架工具&#xff0c;底层切换到了 vite &#xff08;下一代前端工具链&#xff09;&#xff0c;为开发提供极速响应 前置条件&#xff1a;16.0或更高版本的Node.js 安装并执行 create-vue npm init vuelatest2、项目…

MongoDB Compass当前版本及历史版本下载安装

mongoDB compass 当前版本下载 官网 https://www.mongodb.com/try/download/compass 官网下载一般只能下载最新版本。 github https://github.com/mongodb-js/compass MongoDB Compass与MongoDB的版本对应关系 MongoDB CompassMongoDB1.9.12MongoDB 2.6.11 Community

HNU-计算机网络-实验5(自选)-安全相关编程实验

计算机网络 课程综合实验安全相关编程实验&#xff08;RUST&#xff09; 计科210X 甘晴void 202108010XXX 【前言】 这个《课程综合实验》是21级开始新加的实验&#xff0c;之前都没有。具体的可以看实验指导书&#xff0c;是用的19级同学的毕设。我完成的这个实验需要一点点R…