POJ 1182 食物链 (带权并查集 && 向量偏移)
题意 : 中文题就不说题意了……
分析 : 通过普通并查集的整理归类, 能够单纯地知道某些元素是否在同一个集合内。但是题目不仅只有种类之分, 还有种类之间的关系, 即同类以及吃与被吃, 而且重点是题目问的并不是种类是否在一个集合内, 而是考察给出的关系是否矛盾。在解释之前, 先明白一个问题, 对于给出的关系, 如果我不能通过前面的信息来推断出来, 是不是不能够判断现在给出关系的对错?那就将这个信息作为真命题并存储起来, 方便后面判断。有了刚刚前面的陈述, 可以知道两个东西=>
对于这个题目并查集存储的是关系(即同类或吃与被吃) && 只有能够相互之间确立关系的才能合并同一个集合内
那如何使用并查集存储关系呢?题目给出的是两个物种和它们间的关系, 我们可以将给出 的两个物种看成两个并查集的节点, 然后将连接两个节点的边带上相应的权值代表这两个节点之间的关系, 为了通俗和具体一点, 就举例说明, 例如题目给出 1 1 2 (即1和2是同类), 存储步骤以及图示如下
①用一个father数组来存储并查集内的父子关系, 这里用father[1] = 2将1设置为2的父节点。(常规并查集操作)
②用relation数组存储连接这两个点的权值(即关系)relation[1]=x, 这里的x需要进行定义, 这里定义如下 0=>同类、1=>父节点吃子节点、2=>子节点吃夫节点(这样的定义并非随意, 后面绿色文字有说明), 所以刚刚的式子就应该是relation[1]=0。
③知道了单独两个物种的关系, 那这两个物种就属于一个集合了。但是1和2有可能并非是单独的物种, 换句话说就是1和2在合并之前可能就已经属于某一个集合了, 刚刚前面也说到, 一旦在一个集合里面, 那这个集合里面的所有元素都能互相确立关系, 那1和2能够确定关系, 那原来1所在的集合肯定也能和2原来所在的集合之间所有的元素确立关系, 所以这两个集合需要合并!
④也就像刚刚③所说, 1和2有可能并非只是单独个体, 有可能已经和其他元素构成集合, 在合并的过程中, 还需要进行路径压缩才能发挥并查集的高效!
如果做完刚刚说的步骤, 那在每一次给出的关系就能通过并查集的查找来知道这句话是否有错!但是很明显, 因为有了权值的设置, 要进行③的集合合并和④的路径压缩就要同时考虑将relation数组进行相应的变化, 因为relation[k]记录的只是k与父节点的关系, 如果进行了路径压缩, 那relation[k]就要变成k与k所在集合根节点的关系了。接下来就是用到向量的地方了!以下来说说如何使用向量知识, 进行集合合并和路径压缩
集合合并:
如果输入=>R fir sec(fir物种和sec物种有R这种关系), 那我们可以得到的已知条件是 fir 和 sec 所在集合的根节点(假设已经经过路径压缩) Fir_root 和 Sec_root, 假设我们将Sec_root接到Fir_root上, 那就能得到如下图, 则我们所要求的就是红色箭头所指代的relation, 然后将节点进行常规的并查集合并, 就能完成集合合并操作了, 也就是relation[Sec_root] = (relation[fir]+(R-1)-relation[sec]+3)%3, father[sec_root] = fir_root, 这里再说明一下relation计算的式子, %3的原因是要保证值在0~2之间, 由于有-relation[sec]操作, 所以为了避免relation[sec]过大, 使得整条模三的式子为负数, 所以进行+3操作!这里需要注意的是, R只是题目的输入(即1或2), 而我们刚刚定义的relation的取值x只有三种情况, 两者的关系是什么呢?也就是如何用输入的R得到实际我们定义的x?如果输入R=1, 对应的x=0, 而R=2, 对应的x=1, 所以x = R-1就是当前物种fir和sec的关系, 这也就是刚刚说为什么x的那三个值并非随意定义的原因。
路径压缩:
操作呢, 就如下图所示, 可见除了根节点自己所有的节点最后的父亲都是根节点, 同样的, relation的更新也可以采用向量的知识, 代码就是可以先通过递归找到根结点, 然后代码中递归的过程就是下图①~④的过程, 是从根到末尾节点的更新, 具体看代码思考
至此就完成了所有操作, 只要在操作之前判断语句是否和之前给出的关系有矛盾, 具体的还是可以用向量来思考。
留下了递归进行路径压缩中如何变relation 和 判断是否是错误语句这两个问题, 看代码即可, 相信这个是不难思考的!
#include<stdio.h> #include<iostream> using namespace std; ; int father[maxn], relation[maxn], n, k, nCase; int findset(int x)//递归寻找根节点 { if(x == father[x]) return x; int temp = father[x];//temp == x的父节点 father[x] = findset(temp);//继续寻找根节点 relation[x] = ( relation[temp] + relation[x] )%;//通过向量相加可以得出现在x与根节点的关系 return father[x]; } int main(void)£¬ { scanf("%d %d", &n, &k); ; i<=n; i++){ father[i] = i; relation[i] = ; } ; while(k--){ scanf("%d %d %d", &command, &fir, &sec); || sec<= || fir>n || sec>n) ans++; && fir==sec) ans++; else{ int Fir_root = findset(fir); int Sec_root = findset(sec); if(Fir_root != Sec_root){//如果两个物种并不在一个关系, 也就是无法知道关系, 则合并 father[Sec_root] = Fir_root; relation[Sec_root] = ( + (command - ) + relation[fir] - relation[sec] )%; }else{ ) {if(relation[fir] != relation[sec]) ans++;}//如果1就代表同类, 则fir和sec与根的关系应该是一样的 - relation[fir] + relation[sec])% != command- ) ans++;}//如果2就代表fir吃sec即command-1, 左边式子同样根据向量运算得到 } } } printf("%d\n", ans); ; }
POJ 1182 食物链 (带权并查集 && 向量偏移)的更多相关文章
- poj 1182 食物链 带权并查集
食物链是并查集的进阶运用的一道非常经典的题目. 题目如下: 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A, ...
- POJ 2492 A Bug's Life (带权并查集 && 向量偏移)
题意 : 给你 n 只虫且性别只有公母, 接下来给出 m 个关系, 这 m 个关系中都是代表这两只虫能够交配, 就是默认异性, 问你在给出的关系中有没有与异性交配这一事实相反的, 即同性之间给出了交配 ...
- K - Find them, Catch them POJ - 1703 (带权并查集)
题目链接: K - Find them, Catch them POJ - 1703 题目大意:警方决定捣毁两大犯罪团伙:龙帮和蛇帮,显然一个帮派至少有一人.该城有N个罪犯,编号从1至N(N<= ...
- POJ - 2912 Rochambeau (带权并查集+枚举)
题意:有N个人被分为了三组,其中有一个人是开了挂的.同组的人的关系是‘=’,不同组的人关系是‘<’或'>',但是开了挂的人可以给出自己和他人任意的关系.现在要根据M条关系找出这个开了挂的人 ...
- A Bug's Life POJ - 2492 (带权并查集)
A Bug's Life POJ - 2492 Background Professor Hopper is researching the sexual behavior of a rare spe ...
- poj1182 食物链 带权并查集
题目传送门 题目大意:大家都懂. 思路: 今天给实验室的学弟学妹们讲的带权并查集,本来不想细讲的,但是被学弟学妹们的态度感动了,所以写了一下这个博客,思想在今天白天已经讲过了,所以直接上代码. 首先, ...
- POJ 1182 食物链(经典带权并查集 向量思维模式 很重要)
传送门: http://poj.org/problem?id=1182 食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: ...
- poj 1182:食物链(种类并查集,食物链问题)
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 44168 Accepted: 12878 Description ...
- POJ 1182 食物链(种类并查集)
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 63592 Accepted: 18670 Description ...
随机推荐
- 【VS开发】【图像处理】RGB各种格式
RGB格式 RGB组合格式 名字 RGB组合格式 描述 此格式用来匹配PC图形帧缓存.每个像素占据8,16,24或32个位,他们都是组合像素格式,其意为在内存中所有像素数据都是相邻排列的.当使用这些格 ...
- vue--生命周期演示
vue实例的生命周期:https://cn.vuejs.org/v2/guide/instance.html#%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA-Vue-%E5% ...
- 使用new关键字创建对象数组(C#,C++,Java)
今天遇到一个题目 分析下面的代码,判断代码是否有误. using System; namespace Test1 { class Point { public int x; public int y; ...
- MySQL出现 Access denied for user 'root'@'localhost' (using password:YES) 解决办法
1.先停止MySQL服务,然后在MySQL安装目录(我的是C:\Program Files (x86)\MySQL\MySQL Server 5.1)找到my.ini文件,在最后一行添加skip-gr ...
- Ubuntu原生源
#deb cdrom:[Ubuntu 18.04.3 LTS _Bionic Beaver_ - Release amd64 (20190805)]/ bionic main restricted # ...
- 面试mysql表设计要注意啥
面试官:讲讲mysql表设计要注意啥? 引言 大家应该知道烟哥最近要(tiao 咳咳咳),嗯,不可描述! 随手讲其中一部分知识,都是一些烟哥自己平时工作的总结以及经验.大家看完,其实能避开很多坑.而且 ...
- 在springboot中使用拦截器
在springMVC中可以实现拦截器,是通过实现HandlerInterceptor接口,然后在springmvc-web.xml中配置就可以使用拦截器了.在springboot中拦截器也是一样的思想 ...
- js 学习三 Array
1.数组的长度 var sequence = [1, 1, 2, 3, 5, 8, 13]; sequence .length //7 2.字符串转换成数组 string.split() var my ...
- java获取json数组格式中的值
第一种方法: String str = "{'array':[{'id':5,'name':'张三'},{'id':6,'name':'李四'}]}"; JSONArray jso ...
- 搭建CocoaPods远程私有库
1.创建自己的远程私有索引库,用来存放私有框架的.podspec文件,并将其添加到本地索引 我用的仓库是码云(https://gitee.com),用自己的账号新建一个私有仓库,我命名为Private ...