热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

poj1182食物链(并查集经典题)

食物链TimeLimit:1000MSMemoryLimit:10000KTotalSubmissions:124632Accepted:38129Description动物王

食物链

Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 124632 Accepted: 38129
Description

动物王国中有三类动物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&#xff08;1 <&#61; N <&#61; 50,000&#xff09;和K句话&#xff08;0 <&#61; K <&#61; 100,000&#xff09;&#xff0c;输出假话的总数。
Input

第一行是两个整数N和K&#xff0c;以一个空格分隔。
以下K行每行是三个正整数 D&#xff0c;X&#xff0c;Y&#xff0c;两数之间用一个空格隔开&#xff0c;其中D表示说法的种类。
若D&#61;1&#xff0c;则表示X和Y是同类。
若D&#61;2&#xff0c;则表示X吃Y。
Output

只有一个整数&#xff0c;表示假话的数目。
Sample Input

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

Sample Output

3

分析&#xff1a;

本题是并查集的经典题目&#xff0c;对于有冲突的话语需要通过并查集来进行判断。

并查集可以看成集合&#xff0c;集合之间的元素具有某种关系。并查集涉及的操作主要是集合的合并和查询根结点&#xff0c;这里的集合其实就是一条食物链&#xff0c;该集合里面的元素之间存在某种关系&#xff0c;而在存储的时候直接存的是每个结点与根节点的关系&#xff0c;而结点之间的关系则需要公式。那什么时候是当前的话与前面的话有冲突呢&#xff1f;就是
1 若输入1 x y&#xff0c;表明x、y是同类&#xff0c;则它们与根结点的关系必定相同&#xff0c;若不同则说明有冲突。
2 若输入2 x y&#xff0c;表明x、y存在x吃y的关系&#xff0c;则它们在同一条食物链&#xff0c;且x、y两个结点之间有x吃y的关系&#xff0c;如果不是&#xff0c;则说明有冲突。

这里的并查集不仅需要保存结点&#xff0c;还需要保存集合中每个结点与根结点的关系。 难点就是在合并和路径压缩时&#xff0c;怎么改变结点与根结点的关系。 首先来看一下集合之间元素关系转换&#xff0c;看懂这个对后面有一定帮助。

集合之间元素关系转换

这里有A、B、C三类动物&#xff0c;它们之间的关系如下。这里给出两个表格&#xff0c;先简单明确一下存在的关系&#xff0c;以及关系之间的转换。
在这里插入图片描述
参考下表&#xff0c;可以知道如果已知A、B关系&#xff0c;B、C关系&#xff0c;如何得出A、C关系。如果把B看作根结点&#xff0c;A、B看作集合中的两个结点&#xff0c;已知A、B与分别C的关系&#xff0c;如何得到集合中任意两个元素A、B之间的关系&#xff1f;
在这里插入图片描述
我们假设r[A]存的是A->B的关系&#xff0c;r[C]存的是C->B的关系&#xff0c;那A->C的关系其实就是(A->B&#43;B->C)%3,也就是(r[A]&#43;3-r[C])%3.(B看作根结点&#xff0c;如果C->B关系为r[C]&#xff0c;则B->C关系为(3-r[C])%3. )
参考上面那个表的信息&#xff0c;可以知道表达式是正确的。
在这里插入图片描述

路径压缩

下面这张图的意思其实就是如果要把A的根结点变为C&#xff0c;那么A与C的关系就是A与其父节点B的关系&#xff0c;再加上父节点B与根结点C的关系。这样转换的原因是我们存储的是结点与根结点的关系&#xff0c;路径压缩后根结点发生了变化&#xff0c;结点与根结点的关系自然也要发生变化
在这里插入图片描述

合并集合

合并结合是比较难的。
假如我们有x、y两个集合&#xff0c;它们的根结点分别是a和b&#xff0c;我们是这样合并的&#xff1a;把集合x并入集合y&#xff0c;也就是令集合x的根结点a指向b&#xff0c;构成一个新集合&#xff0c;根结点为b。这里就涉及一个问题&#xff0c;我们需要知道a到b的关系。
已知的关系是x->a&#xff1a;r[x]和y->b:r[y]&#xff0c;还有x->y的关系h,
可以知道a->b&#61; a->x &#43; x->b &#61; a->x &#43; h &#43; y->b .
也就是a->b&#61;(3-r[x]&#43;h&#43;r[y])%3
在这里插入图片描述

代码&#xff1a;

#include
#include
using namespace std;
const int N&#61;50001;
int p[N],r[N];
int find(int i){int t;if(i&#61;&#61;p[i]) return i;t&#61;p[i];p[i]&#61;find(p[i]);//路径压缩r[i]&#61;(r[t]&#43;r[i])%3;//更改关系return p[i];
}
void merge(int x,int y,int h)
{int a&#61;find(x),b&#61;find(y);p[a]&#61;b;r[a]&#61;(r[y]-r[x]&#43;3&#43;h)%3;
}//合并集合
int main()
{int n,k,i,ans&#61;0;scanf("%d %d",&n,&k);for(i&#61;1;i<&#61;n;i&#43;&#43;) p[i]&#61;i;while(k--){int d,x,y;scanf("%d %d %d",&d,&x,&y);if(x>n||y>n){ans&#43;&#43;;continue; }if(d&#61;&#61;1){if(find(x)&#61;&#61;find(y)){if(r[x]!&#61;r[y]) ans&#43;&#43;;}else merge(x,y,0);}else{if(find(x)&#61;&#61;find(y)){//if(r[x]!&#61;(r[y]&#43;1)%3) ans&#43;&#43;;if((r[x]&#43;3-r[y])%3!&#61;d-1) ans&#43;&#43;;}else merge(x,y,1);}}printf("%d\n",ans);return 0;
}

更多&#xff1a;

下面这个博客的讲解也很不错&#xff1a;
https://blog.csdn.net/niushuai666/article/details/6981689


推荐阅读
  • 本题探讨如何通过最大流算法解决农场排水系统的设计问题。题目要求计算从水源点到汇合点的最大水流速率,使用经典的EK(Edmonds-Karp)和Dinic算法进行求解。 ... [详细]
  • 使用Vultr云服务器和Namesilo域名搭建个人网站
    本文详细介绍了如何通过Vultr云服务器和Namesilo域名搭建一个功能齐全的个人网站,包括购买、配置服务器以及绑定域名的具体步骤。文章还提供了详细的命令行操作指南,帮助读者顺利完成建站过程。 ... [详细]
  • 本教程涵盖OpenGL基础操作及直线光栅化技术,包括点的绘制、简单图形绘制、直线绘制以及DDA和中点画线算法。通过逐步实践,帮助读者掌握OpenGL的基本使用方法。 ... [详细]
  • 本题涉及一棵由N个节点组成的树(共有N-1条边),初始时所有节点均为白色。题目要求处理两种操作:一是改变某个节点的颜色(从白变黑或从黑变白);二是查询从根节点到指定节点路径上的第一个黑色节点,若无则输出-1。 ... [详细]
  • 本题通过将每个矩形视为一个节点,根据其相对位置构建拓扑图,并利用深度优先搜索(DFS)或状态压缩动态规划(DP)求解最小涂色次数。本文详细解析了该问题的建模思路与算法实现。 ... [详细]
  • 本文介绍了如何通过 Maven 依赖引入 SQLiteJDBC 和 HikariCP 包,从而在 Java 应用中高效地连接和操作 SQLite 数据库。文章提供了详细的代码示例,并解释了每个步骤的实现细节。 ... [详细]
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • 本文探讨了 C++ 中普通数组和标准库类型 vector 的初始化方法。普通数组具有固定长度,而 vector 是一种可扩展的容器,允许动态调整大小。文章详细介绍了不同初始化方式及其应用场景,并提供了代码示例以加深理解。 ... [详细]
  • 本文详细介绍了C语言中链表的两种动态创建方法——头插法和尾插法,包括具体的实现代码和运行示例。通过这些内容,读者可以更好地理解和掌握链表的基本操作。 ... [详细]
  • 尽管使用TensorFlow和PyTorch等成熟框架可以显著降低实现递归神经网络(RNN)的门槛,但对于初学者来说,理解其底层原理至关重要。本文将引导您使用NumPy从头构建一个用于自然语言处理(NLP)的RNN模型。 ... [详细]
  • 探索1000以内的完美数:因数和等于自身
    本文探讨了如何在1000以内找到所有完美数,即一个数的因数(不包括自身)之和等于该数本身。例如,6是一个完美数,因为1 + 2 + 3 = 6。通过编程实现这一过程,可以更好地理解完美数的特性。 ... [详细]
  • Codeforces Round #566 (Div. 2) A~F个人题解
    Dashboard-CodeforcesRound#566(Div.2)-CodeforcesA.FillingShapes题意:给你一个的表格,你 ... [详细]
  • 使用GDI的一些AIP函数我们可以轻易的绘制出简 ... [详细]
  • 毕业设计:基于机器学习与深度学习的垃圾邮件(短信)分类算法实现
    本文详细介绍了如何使用机器学习和深度学习技术对垃圾邮件和短信进行分类。内容涵盖从数据集介绍、预处理、特征提取到模型训练与评估的完整流程,并提供了具体的代码示例和实验结果。 ... [详细]
  • 本文介绍了几种不同的编程方法来计算从1到n的自然数之和,包括循环、递归、面向对象以及模板元编程等技术。每种方法都有其特点和适用场景。 ... [详细]
author-avatar
手机用户2602938185
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有