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

这篇具有很好参考价值的文章主要介绍了并查集维护额外信息,算法思路类似前缀和,结构类似扑克接龙。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、链接

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

六、精美图片

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

 文章来源地址https://www.toymoban.com/news/detail-632226.html

到了这里,关于并查集维护额外信息,算法思路类似前缀和,结构类似扑克接龙的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 算法刷题day34:并查集

    今天写的题集是并查集,其实感觉有两个难点,一个是,要维护多余的信息和路径压缩,另一个难点则是抽象出来合并集合的这个操作,还是要不断地练习,看别人怎么去做,加油! 标签:并查集 思路: 模板题,没啥说的 题目描述: 示例代码: 标签:并查集 思路: 其实

    2024年03月21日
    浏览(64)
  • 算法与数据结构(九)--并查集

    1.处理对象:Disjoint Set,即“不相交集合”。 在一些应用问题中,需将n个不同的元素划分成一组不相交的集合。开始时,每个元素自成一个单元素集合,然后按一定顺序将属于同一组元素的集合合并。其间要反复用到查询某个元素属于哪个集合的运算。适合于描述这类问题的

    2024年02月10日
    浏览(41)
  • 【算法日志】图论 并查集及其简单应用

    并查集是一种算法设计思想,通过判断两个元素是否在同一个集合里,常用来解决一些和图相关的连通性问题。 并查集主要有以下两个功能: 将两个元素添加到一个集合中。 判断两个元素是否是在一个集合之中(这一功能够有效判断是否成环)。 主要思想: 通过创建一个数组

    2024年01月23日
    浏览(48)
  • ⌈算法进阶⌋图论::并查集——快速理解到熟练运用

    目录  一、原理 1. 初始化Init   2. 查询 find  3. 合并 union 二、代码模板 三、练习 1、  990.等式方程的可满足性🟢 2、  1061. 按字典序排列最小的等效字符串🟢 3、721.账户合并 🟡 4、  839.相似字符串组🟡 5、  2812.找出最安全路径 🔴 并查集主要运用与求一些 不相交且有关

    2024年02月13日
    浏览(35)
  • 【算法证明 五】并查集的时间复杂度

    相信如果不是为了刷 leetcode 外,很少有数据结构的数介绍并查集这一数据结构的。并查集的算法模板写起来非常容易,所以刷了并查集相关算法题的人,应该也不会去深入分析这一数据结构,最多知道路径压缩、按秩合并可以做到非常快。深入一点知道 阿克曼函数 α ( n ) 阿

    2024年02月11日
    浏览(46)
  • 罗勇军 →《算法竞赛·快冲300题》每日一题:“小球配对” ← 并查集

    【题目来源】 http://oj.ecustacm.cn/problem.php?id=1850 http://oj.ecustacm.cn/viewnews.php?id=1023 【题目描述】 给定 n 个小球,编号为 1-n ,给定 m 个篮子,编号为 1-m 。 每个球只允许放入样例给定的编号为 Ai 或者 Bi 的两个篮子中的 1 个。 每个球必须放入某个篮子。 如果篮子中球的数量为奇

    2024年02月11日
    浏览(40)
  • [算法分析与设计] 3. 并查集分析与反阿克曼函数

    Union-Find 问题:给定 (n) 个元素,最初每个元素在一个集合中,有两种操作,union 表示合并两个集合,find 表示查询某个特定元素所在的集合。 并查集是一种数据结构。其为每个集合寻找一个代表元,代表元可以是任意的,也可以随操作变化,但需要满足任何时刻一个集合的

    2024年02月08日
    浏览(50)
  • AcWing 算法基础课二 数据结构 链表 栈 队列 并查集 哈希表

    链表题目:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 AcWing. 826.单链表 双链表 AcWing 827.双链表 AcWing 828.模拟栈 AcWing 3302.表达式求值 AcWing 829. 模拟队列 AcWing 830.单调栈 AcWing 154.滑动窗口 AcWing 831. KMP字符串 AcWing 835. Trie字符串统计 AcWing 143. 最大异或对 AcWing 836.合并集合

    2024年02月15日
    浏览(50)
  • 求无向图的最小生成树——Kruskal算法(超详细)【并查集,python实现】

    以如下无向图为例,求最小生成树及其权值。 补充知识点: 最小生成树(不官方的解释):包含所有节点,保持整个图连通,所有边权值之和最小。 1、补充在前 (1)图的存储 采用二维列表存储(点,点,边的权值) (2)顶点转换 为了便于计算,将字母A ~ G用数字0 ~ 6代

    2024年02月04日
    浏览(44)
  • 前缀和算法(类似于动态规划算法)

    前缀和:在一些特定的题里面,要先把 一段连续的数的和 先算出来,用 数组来接收 ,然后 利用这个数组 返回题目需要的答案 干讲无力 题目解释更好 请往下看 题目:题目链接 题目解析: 在数组中找到一个下标,划分为2个区间 左区间的和=右区间的和,如果没有这个下标则返

    2024年02月04日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包