食物链(并查集) 维护权值写法,非常详细,适合新手服用

 题目描述: 

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

A 吃 B,B 吃 C,C吃 A。

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

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

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

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

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

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

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

  1. 当前的话与前面的某些真的话冲突,就是假话;
  2. 当前的话中 X 或 Y比 N 大,就是假话;
  3. 当前的话表示 X 吃 X,就是假话。

你的任务是根据给定的 N 和 K 句话,输出假话的总数。

输入格式

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

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

若 D=1,则表示 X 和 Y 是同类。

若 D=2,则表示 X 吃 Y。

输出格式

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

数据范围

1≤N≤50000,
0≤K≤1000000

输入样例:
100 7
1 101 1 
2 1 2
2 2 3 
2 3 3 
1 1 3 
2 3 1 
1 5 5
输出样例:
3

思路: 

首先我们要知道并查集中每一个集合以树的形式进行存储
此题需要我们维护的信息是d[](节点边的权值)。

 从此图中我们还可以发现,此图为一个有向图且成一个环形状,可以推出3个动物一循环

所以我们只需要知道两个动物的关系,放到集合中,集合中所有动物的关系,我们是一定可以退出来的。


我们思考一个位置,如果推出来的呢? 

例如:x与y是同类,y被z吃,我们是不是可以推出来x也被z吃呢

再比如:x吃y, y吃z,通过上面我们画的有向图,是不是也能推出来z吃x呢。因为是一个环形有向图吗,所以一定可以推出来的这里就不画图了,类比上面的图。


那么我们如何确定一个集合里面的动物之间关系呢? 

我们只需要找出此点根节点之间的关系即可。

例如:如下图


下面我们来看一下代码。 


 AC代码:

//首先我们要知道并查集中每一个集合以树的形式进行存储
//此题需要我们维护的信息是d[](节点边的权值)。
#include <iostream>
#include <cstring>
#include <algorithm>using namespace std;const int N = 5e4+10;
int n,m;
//p[]->存出父亲节点,d[]->i到用来存储到根节点的距离
//刚开始自己一个类所以d[]都是0
int p[N],d[N];//路径压缩,顺势求出每个点到根节点的距离
int find(int x)
{//如果不是根节点就执行if(p[x] != x){//用来存储一下根节点,为了不影响后面求x到根节点的值int t = find(p[x]);//累加求出x(该点)到根节点的值d[x] += d[p[x]];p[x] = t;//指向根节点,路径压缩成功}return p[x];//返回父亲节点
}int main()
{int res = 0;//计算假的个数scanf("%d%d", &n, &m);//刚开始自己为单独一个集合for(int i=1;i<=n;i++) p[i] = i;while (m -- ){int t,x,y;scanf("%d%d%d",&t,&x,&y);//当前的话中 X或 Y比 N大,就是假话 if(x > n || y > n)res ++;else{   //分别求一下两个动物的根节点,为了后面确认关系int px = find(x),py = find(y);//同类if(t==1){//如果在一个根节点下,要保证d[x] % 3 == d[y] % 3 ---> (d[x] - d[y])%3==0if(px == py && (d[x] - d[y])%3) res++;//如果不在一个根节点下else if(px!=py){//不妨让x编号根节点合并到y编号下根节点下。也就是py是px的父亲节点p[px] = py;//d[x] + ? - d[y] = 0 -- > ? = d[y] - d[x];d[px] = d[y] - d[x];}}else//被吃的关系{//如果在一个根节点下,x吃y,第0代被第1代吃,第一代被第二代吃,第三代吃第二代//可以知道x是比y到根节点距离多1的,所以(d[x] - d[y] - 1)%3 = 0;if(px == py && (d[x] - d[y] - 1) % 3) res++;else if(py!=px){p[px] = py;//d[x] + ? - 1 - d[y] = 0 ---> ? = d[y] + 1 - d[x];d[px] = d[y] + 1 - d[x];}}}}printf("%d",res);return 0;
}

上述代码大家可能会疑问,d都初始化为0了,那无论d[x]加多少次d[p[x]],结果都是0啊 ? 

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

我们可以看到此代码,在我们插入两个动物关系的时候,这里已经有+1的操作了,所以我们不用担心这个问题。


 第二个有问题的地方可能是find函数那里

int find( int x ) {
if( p[x] != x ) {
// int t = find( p[x] );
d[x] += d[p[x]];
p[x] = find( p[x] );
}
return p[x];
}

为什么不可以上面那么写,一定要像下面那么写呢?

int find( int x ) {
if( p[x] != x ) {
int t = find( p[x] );
d[x] += d[p[x]];
p[x] = t;
}
return p[x];
}

这里推荐大家手动模拟一遍,然后看一下两者的区别,第一种只能去求出到父亲节点的距离,并不能够达到累加求到根节点的距离,相比之下,第二种可以。 


对于这段代码图解:


对于这段代码图解:

 注意X到根的距离比Y多1,因为是X吃Y,可以根据上面图理解一下


对于find函数里的递归如下:

此图来源于acwing题解中一位大佬的图解,原图在:AcWing 240. 食物链---数组d的真正含义以及find()函数调用过程 - AcWing


欢迎不会的小伙伴留言~ 

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

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

相关文章

微信小程序开发学习笔记——4.6tabBar底部tab栏配置用法

>>跟着b站up主“咸虾米_”学习微信小程序开发中&#xff0c;把学习记录存到这方便后续查找。 一、tabBar https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html#tabBar 二、icon下载 https://www.iconfont.cn/collections/index?spma…

html基础(一文读懂html常用标签)

1.html简介 html是一种用于创建网页的标记语言。它由一系列的标签&#xff08;tags&#xff09;组成&#xff0c;这些标签定义了网页的结构和内容。HTML被用来描述网页的各种元素&#xff0c;比如标题、段落、图像、链接等。 小tips&#xff1a;html 代码可以热更新&#xff…

NSSCTF Round#20 Basic 真亦假,假亦真 CSDN_To_PDF V1.2 出题笔记 (附wp+源码)

真亦假&#xff0c;假亦真 简介&#xff1a;java伪造php一句话马。实则信息泄露一扫就出&#xff0c;flag在/flag里面。 题目描述&#xff1a;开开心心签个到吧&#xff0c;祝各位师傅们好运~ 静态flag&#xff1a;NSS{Checkin_h4v3_4_g00D_tINNe!} /路由显示 <?php e…

2024年03月CCF-GESP编程能力等级认证Scratch图形化编程一级真题解析

本文收录于专栏《Scratch等级认证CCF-GESP真题解析》,专栏总目录・点这里 一、单选题(每题 3 分,共 30 分) 第1题 小杨的父母最近刚刚给他买了一块华为手表,他说手表上跑的是鸿蒙,这个 鸿蒙是?( )。 A、小程序 B、计时器 C、操作系统 D、神话人物 答案:C 第2题 …

网络升级固件

资源信息 可知 &#xff1a; install\soc_cv1800b_milkv_duo_sd\boot.sd文件较设备中的同名文件多了128个字节的文件头&#xff1b;install\soc_cv1800b_milkv_duo_sd\rawimages\boot.sd文件与设备中同名文件相同&#xff1b; 环境搭建 服务器 启动TFTP服务 安装TFTP服务器…

手机有线投屏到直播姬pc端教程

1 打开哔哩哔哩直播姬客户端并登录(按下图进行操作) 2 手机用usb数据线连接电脑(若跳出安装驱动的弹窗点击确定或允许),usb的连接方式为仅充电(手机差异要求为仅充电),不同品牌手机要求可能不一样,根据实际的来 3 在投屏过程中不要更改usb的连接方式(不然电脑会死机需要重启) …

0基础学习Mybatis系列数据库操作框架——多环境配置

大纲 配置代码 在实际开发中&#xff0c;我们往往会将开发环境分成&#xff1a;开发、测试、线上等环境。这些环境的数据源不一样&#xff0c;比如开发环境就不能访问线上环境&#xff0c;否则极容易出现线上数据污染等问题。Mybatis通过多环境配置分开定义来解决这个问题&…

TCP和UDP区别和使用场景

TCP 和 UDP 是计算机⽹络中两种常⽤的传输层协议&#xff0c;⽤于实现可靠传输和⽆连接传输。 TCP TCP&#xff08;Transmission Control Protocol&#xff09;是⼀种⾯向连接的、可靠的传输协议。它通过三次握⼿四次挥⼿进⾏连接和断开链接&#xff0c;保证数据的可靠性、…

JAVA基础02-Java语言基础以及编译准备工作

什么是JAVA语言 Java是一门面向对象的编程语言&#xff0c;不仅吸收了C语言的各种优点&#xff0c;还摒弃了C里难以理解的多继承、指针等概念&#xff0c;因此Java语言具有功能强大和简单易用的两个特征。 &#xff08;可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式…

​慧天[HTWATER]可以与与SWMM模型之间实现转换吗?

​慧天[HTWATER]软件简介 针对城市排水系统基础设施数据管理的需求&#xff0c;以及水文、水力及水质模拟对数据的需求&#xff0c;实现了以数据库方式对相应数据的存储。可以对分流制排水系统及合流制排水系统进行地表水文、管网水力、水质过程的模拟计算。可以对城市低影响开…

【学习笔记】java项目—苍穹外卖day02

文章目录 苍穹外卖-day02课程内容1. 新增员工1.1 需求分析和设计1.1.1 产品原型1.1.2 接口设计1.1.3 表设计 1.2 代码开发1.2.1 设计DTO类1.2.2 Controller层1.2.3 Service层接口1.2.4 Service层实现类1.2.5 Mapper层 1.3 功能测试1.3.1 接口文档测试1.3.2 前后端联调测试 1.4 …

SwiftUI Swift 显示隐藏系统顶部状态栏

Show me the code // // TestHideSystemTopBar.swift // pandabill // // Created by 朱洪苇 on 2024/4/1. //import SwiftUIstruct TestHideSystemTopBar: View {State private var isStatusBarHidden falsevar body: some View {Button {withAnimation {self.isStatusBa…