算法:食物链(并查集)
并查集
1.将两个集合合并
2.询问两个元素是否在一个集合当中
基本原理:每个集合用一棵树来表示。树根的编号就是整个集合的编号。每个节点存储它的父节点,p[x]表示x的父节点。
问题1:如何判断树根:if(p[x] == x)
问题2:如何求x的集合编号:while(p[x]!=x)x=p[x]
问题3:如何合并两个集合:px是x的集合编号,py是y的集合编号。p[x] = y
当前问题用d[x]表示到它根节点的距离。由于有三种物种,
- 当x,y在同一集合中时,我们用
(d[x] - d[y]) % 3 = 0
来表示x,y为同类 - 当x,y在同一集合中时,我们用
(d[x] - d[y] % 3 =1)
来表示x吃y - 当x,y在同一集合中时,我们用
(d[x] - d[y] % 3 = 2)
来表示y吃x
当两个物种不在同一集合中时,意味着还不能通过之前的话,来判断当前两个物种之间的关系,所以需要通过当前给的条件将这两个物种所在的集合合并。
合并时,当条件说明这两个物种是同类时,说明(d[x] - d[y] + ?) % 3=0
, ?为两个集合根节点的距离。? = d[y] - d[x]
。
当条件说明这两个物种x吃y时,说明(d[x] + ? - d[y] - 1) % 3 = 0
,故? = d[y] - d[x] + 1
。
问题描述
动物王国中有三类动物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≤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;
int p[50010],d[50010];
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;cin >> n >> m;for(int i = 1; i <= n; ++i){p[i] = i;}int res = 0;while(m--){int t, x, y;cin >> 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 != 0){res++;}else if(px != py){p[px] = py;d[px] = d[y] - d[x];}}else{if(px == py && (d[x] - d[y] - 1) % 3a{res++; }else if(px != py){p[px] = py;d[px] = d[y] + 1 - d[x];}}}}cout << res << endl;return 0;
}
原题链接
算法:食物链(并查集)相关推荐
- Noi2001食物链-并查集
Noi2001食物链-并查集 1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #incl ...
- Kruskal算法与并查集
Kruskal算法与并查集 一.Kruskal算法 1. 概念 Kruskal算法就是按照图中各个边上的权值大小进行递增排序,以此来构造最小生成树. 2.重点解析 在由Kruskal实现最小生成树的过 ...
- poj 1182 食物链 并查集
转自一位大佬的最全题解 https://blog.csdn.net/c0de4fun/article/details/7318642 #include <cstdio> #include ...
- POJ 1182 食物链 [并查集 带权并查集 开拓思路]
传送门 P - 食物链 Time Limit:1000MS Memory Limit:10000KB 64bit IO Format:%I64d & %I64u Submit ...
- 简单易懂的并查集算法以及并查集实战演练
文章目录 前言 一.引例 二.结合引例写出并查集 1. 并查集维护一个数组 2. 并查集的 并 操作 3. 并查集的 查 操作 4. 基本并查集模板代码实现--第一版(有错误后面分析) 4.1 Jav ...
- 算法总结 — 并查集
参考:算法学习笔记(1) : 并查集 - 知乎 并查集 (disjoint set union) 是 最优美的数据结构之一 合并 (merge): 把两个集合合并 查找 (find): 查找一个元素的 ...
- 【算法】并查集的运用
并查集的概念 朋友圈 团伙问题 连通图 总结 并查集的概念 并查集顾名思义就是合并和查找,问题在于合并什么,查找什么.这里有一种朴素的思想来解释这两个问题.就是把这个想成一棵树.合并什么?就是把不在这 ...
- 算法:并查集(四种方式)
简单并查集 public class UnionFind {private int[] id;private int count;public UnionFind(int N) {count = N; ...
- Kruskal算法和并查集
Kruskal算法 步骤: 第一步:给所有边按照从小到大顺序排列(直接使用库函数qsort / sort). 第二步:从小到大依次考察每条边(u,v),在执行第二步时会出现以下两种情况: 情况1:u和 ...
- Java实现_算法_并查集
并查集 作用:用来查找某个图中是否含有闭环. 比如图一: 上图中就是没有闭环的一个图,而下图(图二)就是一个有闭环的图 思路1-数组寻根法: 顾名思义,数组寻根法(自己称呼的)就是寻找每个节点的根节点 ...
最新文章
- 皮一皮:这是结婚还是华山论剑...
- jsp页面引用相关js,css文件路径问题
- linux 下执行python.py 无效解决方案
- Android环境配置(Eclipse全开发环境下载)
- DEDECMS添加友情链接长度限制的详细解决方法
- 【智能制造】智能制造将势不可挡
- 3D标签云效果的实现
- Excel 中如何去掉数值中出现的 E +,网上的方法都试过了不管用,改变单元格格式等都无效
- 阿里P8、P9税后180W及以上到底是什么水平?
- 黑马程序员顺义校区php_PHP面向对象开发视频教程[黑马程序员]
- 基于Python小说电子书阅读系统设计与实现 开题报告
- 【原创】Xilinx:K7 DDR3 IP核配置教程
- 智能视频分析监控技术
- 后端文件流在浏览器pdf预览
- 网站服务器更新申请,网站服务器申请
- 产品经理必备的20个常用工具
- linux下的几种输入法下载地址
- VC操作word和excel文件,查询与读写[依赖office环境]
- AD20在pcb设计时,器件如何旋转特定角度
- 2021-2027全球与中国反射式空间光调制器市场现状及未来发展趋势
热门文章
- 【系统架构设计师】第一章:操作系统(1.2.2) 信号量与pv操作
- stack-es-标准篇-ElasticsearchClient-fields
- DRM之Microsoft PlayReady学习入门(一)
- ind2vec和vec2ind函数用法
- https://blog.csdn.net/qq_35992900/article/details/80673889
- K210 only support kmodel V3/V4 now
- 华为交换机配置接口安全
- 一行代码“黑”掉任意网站
- GK888CN与Devexpress报表打印标签
- 关于python类说法正确的是_关于Python的说法正确的是