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

一、链接

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

六、精美图片

 

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

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

相关文章

Nginx使用proxy_cache指令设置反向代理缓存静态资源

场景 CentOS7中解压tar包的方式安装Nginx&#xff1a; CentOS7中解压tar包的方式安装Nginx_centos7 tar文件 怎么load_霸道流氓气质的博客-CSDN博客 参考上面流程实现搭建Nginx的基础上&#xff0c;实现静态资源的缓存设置。 注意上面安装时的目录是在/opt/nginx目录下&…

数组的学习

数组学习 文章目录 数组来由数组的使用数组的内存图变量声明和args参数说明声明分配空间值的省略写法数组的length属性数列输出求和判断购物金额结算Arrays的sort和toString方法Arrays的equals和fill和copyOf和binarySearch方法字符数组顺序和逆序输出 数组来由 录入30个学生…

Linux(进程)

Linux&#xff08;进程&#xff09; 1. 冯诺依曼结构体系2 . 操作系统&#xff08;OS&#xff09;3.进程task_ struct内容分类查看进程查看PID以及PPIDfork()Linux操作系统进程的状态僵尸进程孤儿进程进程优先级其他概念 1. 冯诺依曼结构体系 冯诺依曼结构也称普林斯顿结构&am…

FastAPI 构建 API 高性能的 web 框架(一)

如果要部署一些大模型一般langchainfastapi&#xff0c;或者fastchat&#xff0c; 先大概了解一下fastapi,本篇主要就是贴几个实际例子。 官方文档地址&#xff1a; https://fastapi.tiangolo.com/zh/ 1 案例1:复旦MOSS大模型fastapi接口服务 来源&#xff1a;大语言模型工程…

云计算——ACA学习 云计算概述

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​ 目录 写在前面 上章回顾 本章简介 本章目标 一.云计算产生背景 1.信息时代的重点变革…

shell中的函数

整理思维导图 写一个函数&#xff0c;获取用户的uid和gid并使用变量接收 #!/bin/bashfunction get() {userwhoamiuidid -u $usergidid -g $userecho "该用户的uid为$uid"echo "该用户的gid为$gid"} get整理冒泡排序、选择排序和快速排序的代码 冒泡排序 #…

【Hystrix技术指南】(1)基本使用和配置说明

这世间许多事物皆因相信而存在&#xff0c;所以人们亲手捏出了泥菩萨&#xff0c;却选择坚定的去信仰它。 分布式系统的规模和复杂度不断增加&#xff0c;随着而来的是对分布式系统可用性的要求越来越高。在各种高可用设计模式中&#xff0c;【熔断、隔离、降级、限流】是经常被…

阿里云平台注册及基础使用

首先进入阿里云官网&#xff1a; 阿里云-计算&#xff0c;为了无法计算的价值 点击右上角“登录/注册”&#xff0c;如果没有阿里云账号则需要注册。 注册界面&#xff1a; 注册完成后需要开通物联网平台公共实例&#xff1a; 注册成功后的登录&#xff1a; 同样点击右上角的…

Self-Attention、transformer代码、word2vec理论(skip-gram、CNOW)、近似训练 (第十三次组会)

@[TOC](Self-Attention、transformer代码、word2vec理论(skip-gram、CNOW)、近似训练 (第十三次组会)) Self-Attention相关 Transformer代码

vue2 todoapp案例(静态)

1.创建三个子组件(TodoHeader、TodoMain、TodoFooter)和两个(index.css、base.css)样式&#xff1b; TodoHeader页面 <template><header class"header"><h1>todos</h1><input id"toggle-all" class"toggle-all" typ…

使用gpt对对话数据进行扩增,对话数据扩增,数据增强

我们知道一个问题可以使用很多方式问&#xff0c;但都可以使用完全一样的回答&#xff0c;基于这个思路&#xff0c;我们可以很快的扩增我们的数据集。思路就是使用chatgpt或者gpt4生成类似问题&#xff0c;如下&#xff1a; 然后我们可以工程化这个过程&#xff0c;从而快速扩…

IP核之fifo

一.FIFO简介 FIFO (First In First Out&#xff0c;即先入先出&#xff09;&#xff0c;是一种数据缓冲器&#xff0c;用来实现数据先入先出的读写方式。 二&#xff0c;FIFO实现原理 FIFO是采用一种先入先出的实现原理 就如图按照D1到D10的顺序输入那么读取的时候也是按照D…

Python(七十二)集合的相关操作(增删改查)

❤️ 专栏简介&#xff1a;本专栏记录了我个人从零开始学习Python编程的过程。在这个专栏中&#xff0c;我将分享我在学习Python的过程中的学习笔记、学习路线以及各个知识点。 ☀️ 专栏适用人群 &#xff1a;本专栏适用于希望学习Python编程的初学者和有一定编程基础的人。无…

FL Studio Producer Edition 21 v21.0.3 Build 3517 Windows/mac官方中文版

FL Studio Producer Edition 21 v21.0.3 Build 3517 Windows FL Studio Producer Edition 21 v21.0.3 Build 3517 Windows/mac官方中文版是一个完整的软件音乐制作环境或数字音频工作站&#xff08;DAW&#xff09;。它代表了 25 多年的创新发展&#xff0c;将您创作、编曲、录…

Framework才是Android 开发的热门技术~

相信大家都有感觉到今年的市场竞争的激烈&#xff0c;投出简历并不像往年一样立马就有回应&#xff0c;大多是这种情况&#xff1a;投出简历没有停歇&#xff0c;状态却是70%未读&#xff0c;30%已读。 这种情况并不是说市场落寞了&#xff0c;不招人了&#xff0c;而是经过了…

【Datawhale AI 夏令营第二期】AI 量化模型预测挑战赛

文章目录 赛题分析赛题背景赛事任务赛题数据集评价指标 Baseline实践导入模块EDA特征工程模型训练与验证结果输出 改进 赛题分析 赛题背景 量化金融在国外已经有数十年的历程&#xff0c;而在国内兴起还不到十年。这是一个极具挑战的领域。量化金融结合了数理统计、金融理论、…

Spring Boot如何整合mybatisplus

文章目录 1. 相关配置和代码2. 整合原理2.1 spring boot自动配置2.2 MybatisPlusAutoConfiguration2.3 debug流程2.3.1 MapperScannerRegistrar2.3.2MapperScannerConfigurer2.3.3 创建MybatisPlusAutoConfiguration2.3.4 创建sqlSessionFactory2.3.5 创建SqlSessionTemplate2.…

springboot 集成 mybatis-plus 代码生成器

springboot 集成 mybatis-plus 代码生成器 一、导入坐标依赖二、配置快速代码生成器三、自定义代码生成器模板 一、导入坐标依赖 前置依赖&#xff0c;需要用到 mybatis,mysql驱动,lombok插件以及swapper.(因为后面接口测试文档&#xff0c;所以swapper也配了) <dependenc…

redis原理 5:同舟共济 —— 事务

为了确保连续多个操作的原子性&#xff0c;一个成熟的数据库通常都会有事务支持&#xff0c;Redis 也不例外。Redis 的事务使用非常简单&#xff0c;不同于关系数据库&#xff0c;我们无须理解那么多复杂的事务模型&#xff0c;就可以直接使用。不过也正是因为这种简单性&#…

Java实现Google cloud storage 文件上传,Google oss

storage 控制台位置 创建一个bucket 点进bucket里面&#xff0c;权限配置里&#xff0c;公开访问&#xff0c;在互联网上公开&#xff0c;需要配置角色权限 新增一个访问权限 &#xff0c;账号这里可以模糊搜索&#xff0c; 角色配置 给allUser配置俩角色就可以出现 在互联…