并查集维护额外信息,算法思路类似前缀和,结构类似扑克接龙

一、链接

240. 食物链

二、题目

动物王国中有三类动物 A,B,CA,B,C,这三类动物的食物链构成了有趣的环形

AA 吃 BB,BB 吃 CC,CC 吃 AA。

现有 NN 个动物,以 1∼N1∼N 编号

每个动物都是 A,B,CA,B,C 中的一种,但是我们并不知道它到底是哪一种。

有人用两种说法对这 NN 个动物所构成的食物链关系进行描述:

第一种说法是 1 X Y,表示 XX 和 YY 是同类

第二种说法是 2 X Y,表示 XX  YY。

此人对 NN 个动物,用上述两种说法,一句接一句地说出 KK 句话,这 KK 句话有的是真的,有的是假的。

当一句话满足下列三条之一时,这句话就是假话,否则就是真话

  1. 当前的话与前面的某些真的话冲突,就是话;
  2. 当前的话中 XX 或 YY  NN 大,就是话;
  3. 当前的话表示 XX 吃 XX,就是话。

你的任务是根据给定的 NN 和 KK 句话,输出假话的总数

输入格式

第一行是两个整数 NN 和 KK,以一个空格分隔。

以下 KK 行每行是三个正整数 D,X,YD,X,Y,两数之间用一个空格隔开,其中 DD 表示说法的种类。

若 D=1D=1,则表示 XX 和 YY 是同类。

若 D=2D=2,则表示 XX 吃 YY。

输出格式

只有一个整数,表示假话的数目。

数据范围

1≤N≤500001≤N≤50000,
0≤K≤1000000≤K≤100000

输入样例:

100 7
1 101 1 
2 1 2
2 2 3 
2 3 3 
1 1 3 
2 3 1 
1 5 5

输出样例:

3

三、题意

总共有三种生物,构成一个吃与被吃的闭环,给出多个描述,判断假话的个数并输出

四、代码

#include<iostream>using namespace std;const int N=50000+10;int p[N],d[N];int find(int x)
{if(p[x]!=x){int t=find(p[x]);d[x]+=d[p[x]];p[x]=t;}return p[x];
}int main()
{int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){p[i]=i;}int res=0;while(m--){int t,x,y;scanf("%d%d%d",&t,&x,&y);if(x>n||y>n){res++;}else{int px=find(x),py=find(y);if(t==1){if(px==py&&(d[x]-d[y])%3){res++;}else if(px!=py){p[px]=py;d[px]=d[y]-d[x];}}else{if(px==py&&(d[x]-d[y]-1)%3){res++;}else if(px!=py){p[px]=py;d[px]=d[y]-d[x]+1;}}}}printf("%d\n",res);return 0;
}

五、总结

1.首先我为什么说这里使用并查集和前缀和的思路类似呢,因为我们在这里使用一个类似预处理的操作,把每一个结点到根节点的距离计算了出来,然后判断这两个节点的距离即可,前缀和是预处理前面的和,然后对两个点的和进行差运算,感觉是差不多的。

2.我们除了合并属于不同集合的元素,还需要维护一些额外的信息,比如说每一个节点到根节点的距离,怎么表示两个元素之间的关系呢,可以看它与根节点之间的距离。

3.先给出一个并查集的模板:并查集模板-两个操作:合并集合和查询两个元素是否属于同一个集合

4.还是有一个问题,就是我们改变一个变量的时候要注意,是否之前对他进行了修改,修改之后我们这样写会报错,所以最好是先把需要使用的变量用一个临时变量存下来,就是这里的几行代码需要注意给这个问题

int t=find(p[x]);
d[x]+=d[p[x]];
p[x]=t;

如果先改变根节点,根节点重合,原来元素到根节点的距离就会发生变化,但是我们需要之前元素到修改之前根节点的距离,所以需要先把根节点拿出来保存,先修改结点到根节点的距离,再修改根节点 

总结就是遇到类似的问题,最好就是把变量拿出来,防止修改之后发生变化,出现错误

5.这个题目需要进行的条件判断比较多:首先是正常的初始化,就是并查集的简单初始化,需要注意的是最开始每一个元素自己相当于根节点,到根节点的距离是0,定义为全局变量,不需要进行初始化。

6.如果第二个或者第三个输入的元素大于输入的总数n,那么就要把假话数字增加一,除去这种情况,再开始讨论别的情况

7.如果是表示的两个属于同类,需要进行两个判断,第一个判断是这两个动物是不是属于同一个集合(并查集的特性),如果属于同一个集合并且两个动物(或者说结点)不是同一类物种(到根节点之间的距离对3进行取模之后的数值不相等),就说明不是真话,res++;如果不属于同一个集合,说明两个元素的集合不是同一个集合,就需要把两个元素合并到同一个集合里面,还需要更新里面结点到根节点的距离,因为根节点发生了变化。在最开始条件判断之前,先把输入的第二个数,第三个数的根节点拿了出来,存在px,py里面,现在更新的话,其实不用太考虑顺序,直接更新结点和距离就可以。更新节点使用这一行代码

p[px]=py;

更新距离需要思考一下,原来结点到根节点的距离是d[x],另一个结点到它的根节点的距离是d[y],我们现在把x的根节点指向了y的根节点,现在y的根节点变成了总的根节点,x和y属于同类,那么他们两个元素到根节点的距离取模之后是相等的,现在x到根节点的距离是d[x]+d[px],d[px]表示的是x的根节点到现在新的根节点的距离,d[x]+d[px]-d[y]取模之后的结果应该是等于0,所以把距离更新的代码就是这样写

d[px]=d[y]-d[x];

 8.另外一种情况是x吃y:并查集里面的树状结构有点像扑克接龙游戏,只能是固定的顺序,一层可以有很多同类的,但是新的不同类的必须在下一层,假设根节点是A,然后B吃A,是第一层,C吃B,是第二层,D和A同类,排在第三层,可以吃C,也可以被B吃,如果再来一个A的同类,这个时候还是排在第三层,如果是x吃y,x假设紧靠着y的话,是排在y的下一层,取模来看的话,是模3之后比y到根节点的距离模3之后大1。分两种情况,第一种情况,x和y在一个并查集里面,并且这两个节点的到根节点的距离的差减去1对3取模(d[x]-d[y]-1)%3不等于0,表示这两个元素不符合x吃y,说明是假话,就把答案增加1。第二种情况是,两个元素不属于同一个并查集,就需要更新根节点和距离,因为在最开始的时候,把两个元素的根节点取出来存在临时变量px,py中,现在操作只需要把根节点更新,把距离更新就行,顺序不需要考虑,更新之后d[x]==d[px]+d[x],应该还是要满足(d[x]-d[y]-1)%3==0,d[px]+d[x]-d[y]-1=0,所以d[px]=d[y]+1-d[x];

9.最后输出答案即可

10.这个题目还是蛮复杂的,抽象的来理解还是比较简单,但是具体构建这个模型,讲述清楚还是比较难,也有可能是我太弱了(肯定是的哈哈)。树状结构真的抽象!简单的来说就是并查集+维护一个到根节点的距离,维护距离的时候注意根节点会发生变化,最好把根节点用临时变量先存起来,再更新根节点和距离

六、精美图片

 

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

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

相关文章

使用RANSAC算法在点云中拟合原始3D形状:pyRANSAC-3D的介绍和应用

随机样本共识(RANSAC)是一种强大的算法,用于从数据集中估计数学模型的参数,特别是在数据包含大量异常值时。在3D计算机视觉中,RANSAC常用于从点云数据中拟合原始形状,例如平面、长方体和圆柱体。本文将介绍一个名为pyRANSAC-3D的开源库,它提供了RANSAC算法的Python实现,…

总结950

7:00起床 7:30~8:00复习单词300个&#xff0c;记忆100个 8:10~9:30数学660&#xff0c;只做了10道题&#xff0c;发现对各知识点的掌握程度不一。有些熟练&#xff0c;有些生疏 9:33~10:25计算机网络课程1h 10:32~12:02继续660&#xff0c;也不知道做了几道 2:32~4:00数据…

12.物联网操作系统之多任务核心

一。列表及列表项概念以及应用 1.freeRTOS列表介绍 列表项都是由链表生成&#xff0c;想要了解列表项&#xff0c;首先应该把上述的链表都要搞懂。 这是列表项的组件列表。 2.列表及列表项的定义 列表是双向链表构成&#xff0c;原因是双向链表的插入与删除效率高&#xff0c…

nodejs 读写 ini

依赖项 需要提前安装 node-gyp , node-gyp 只要有对应版本的 python 与 c 环境, 应该就没啥问题了. "devDependencies": {"types/node": "^20.4.8","types/ffi-napi": "^4.0.7", "ffi-napi": "^4.0.3&quo…

分布式 - 服务器Nginx:常见问题总结(二)

文章目录 01. Nginx 虚拟主机怎么配置?02. Nginx location 指令的作用&#xff1f;03. Nginx location 指令如何与其他指令一起使用&#xff1f;04. Nginx root 命令的作用&#xff1f;05. Nginx if 模块的作用&#xff1f;06. Nginx include 指令的作用&#xff1f;07. Nginx…

ThinkPHP函数深度解析

ThinkPHP是一个具有丰富功能和强大灵活性的PHP开发框架。在这篇文章中&#xff0c;我们将详细介绍ThinkPHP的一些关键函数&#xff0c;以帮助开发人员更好地理解和使用这个框架。 1. 入门&#xff1a;ThinkPHP的核心函数 1.1 C()函数 C()函数用于读取和设置配置参数。它是Thin…

【Spring】使用注解的方式获取Bean对象(对象装配)

目录 一、了解对象装配 1、属性注入 1.1、属性注入的优缺点分析 2、setter注入 2.1、setter注入的优缺点分析 3、构造方法注入 3.1、构造方法注入的优缺点 二、Resource注解 三、综合练习 上一个博客中&#xff0c;我们了解了使用注解快速的将对象存储到Spring中&#x…

Android:自己写一个简单记事本

一、前言&#xff1a;我的app是点击加号跳转到另一个界面 那么我遇到的问题的是点击加号是一个从一个Fragment跳转到另一个Fragment跳转失败。 二、解决方案&#xff1a; //相应控件的监听里面实现跳转FragmentManager fragmentManagergetFragmentManager();fragmentManager.b…

网络可靠性之链路聚合

网络的可靠性 网络的可靠性指当设备或者链路出现单点或者多点故障时保证网络服务不间断的能力网络的可靠性是可以从单板、设备、链路多个层面实现。 链路聚合 以太网链路聚合&#xff1a; 通过将多个物理接口捆绑成为一个逻辑接口&#xff0c;可以再不进行硬件升级的条件下&a…

css滚动条样式指南

css滚动条样式指南 滚动条是网页设计中经常被忽视的元素。虽然它看起来像是一个小细节&#xff0c;但它在网站导航中起着至关重要的作用。默认的滚动条可能看起来不合适&#xff0c;有损整体美观。本文将介绍如何使用 CSS 自定义滚动条。 在 Chrome、Edge 和 Safari 中设置滚…

【Rust 基础篇】Rust类函数宏:代码生成的魔法

导言 Rust是一门现代的、安全的系统级编程语言&#xff0c;它提供了丰富的元编程特性&#xff0c;其中类函数宏&#xff08;Function-Like Macros&#xff09;是其中之一。类函数宏允许开发者创建类似函数调用的宏&#xff0c;并在编译期间对代码进行生成和转换。在本篇博客中…

基于Azure OpenAI Service 的知识库搭建实验⼿册

1.概要 介绍如何使⽤Azure OpenAI Service 的嵌⼊技术&#xff0c;创建知识库&#xff1b;以及创建必要的资源组和资源&#xff0c;包括 Form Recognizer 资源和 Azure 翻译器资源。在创建问答机器⼈服务时&#xff0c;需要使⽤已部署模型的 Azure OpenAI 资源、已存在的…

SAP-MM-发票校验的重复校验功能

路径&#xff1a;SPRO-物料管理-后勤发票校验-收入发票-设置重复发票检查 按公司代码设置重复检查&#xff0c;可以按三个方式进行检查&#xff0c;公司代码、参照、发票日期&#xff0c;如果此处未维护就是按供应商&#xff08;XK02&#xff09;的六项进行检查 但是如果两处都…

MySQL 中的 distinct 和 group by 哪个效率更高?

在 MySQL 中&#xff0c;DISTINCT 和 GROUP BY 都是用来去除重复的数据&#xff0c;但它们的使用场景和性能影响是不同的。 有索引的情况下 group by 和 distinct 都能使用索引&#xff0c;效率相同。 无索引的情况下 distinct 效率高于 group by。原因是 distinct 和 group …

深入学习 Redis - 事务、实现原理、指令使用及场景

目录 一、Redis 事务 vs MySQL事务 二、Redis 事务的执行原理 2.1、执行原理 2.2、Redis 事务设计这么简单&#xff0c;为什么不涉及成 MySQL 那样强大呢&#xff1f; 三、Redis 事务的使用 3.1、使用场景 3.2、具体演示 开启/执行/放弃事务 watch 监控 watch 实现原理…

chapter14:springboot与安全

Spring Boot与安全视频 Spring Security, shiro等安全框架。主要功能是”认证“和”授权“&#xff0c;或者说是访问控制。 认证&#xff08;Authentication&#xff09;是建立在一个声明主体的过程&#xff08;一个主体一般指用户&#xff0c;设备或一些可以在你的应用程序中…

nginx配置访问springboot服务

一、idea中可通过 clean package打包命令&#xff0c;打好包 ,比如&#xff1a;端口为8080&#xff0c;服务访问地址为/&#xff0c; 前端打包文件为dist&#xff0c;访端口为8000&#xff0c; 则可以这样配置nginx server {listen 8000;location / {root html/dist;…

ASP.NET Core SignalR

ASP.NET Core SignalR是一个开发实时网络应用程序的框架&#xff0c;它使用WebSocket作为传输协议&#xff0c;并提供了一种简单和高效的方式来实现实时双向通信。 SignalR使用了一种称为"Hub"的概念来管理连接和消息的传递。开发者可以编写自己的Hub类&#xff0c;…

Django之JWT库与SimpleJWT库的使用

Django之JWT库与SimpleJWT库的使用 JWTJWT概述头部(header)载荷(payload)签名(signature) Django使用JWT说明jwt库的使用安装依赖库配置settings.py文件配置urls.py文件创建视图配置权限 SimpleJWT库的使用安装SimpleJWT库配置Django项目配置路由创建用户接口测试身份认证自定义…

【雕爷学编程】Arduino动手做(190)---MAX4466声音模块

37款传感器与模块的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&#x…