POJ 1182 食物链(经典并查集) (多组输入有时乱加也会错!)
| Time Limit: 1000MS | Memory Limit: 10000K | |
| Total Submissions: 68854 | Accepted: 20363 |
Description
现有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(1 <= N <= 50,000)和K句话(0 <= K <= 100,000),输出假话的总数。
Input
以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。
若D=1,则表示X和Y是同类。
若D=2,则表示X吃Y。
Output
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
Source
题意:一共就三种动物,如果A吃B,B吃C==》C吃A;
A吃B,A吃C==》B、C为同类
A被B吃,A被C吃==》B、C为同类
用并查集来做:
两种动物之间的关系通过于根节点的相对关系得出,所以关键是路径压缩与合并两个集合时的动物与根节点相对关系的变化,其实也可认为是一个问题,因为路径压缩中的变化其实是合并集合产生的子问题。
用delta【i】来表示i和i的父节点的关系,rank[i]=0/1/2分别表示 i 与父亲是同类、被父亲吃、吃父亲。
先讲合并操作:
设tx为x的父亲,ty是y的父亲,所以delta[x]表示x和tx的关系,delta[y]表示y与ty的关系,现在,合并操作要将ty的父亲置为tx,所以delta[ty]的值就要发生相应的改变,即产生了新的ty与tx的关系;
那么,如何求这个关系呢?有两种方法:第一种,可以通过实际数据推出来,
tx ty
| |
x ~ y
知道了tx与x的关系,x与y的关系,y与ty的关系,tx与ty的关系自然就推出来了
type表示x与y的关系0为同类,1为x吃y
| type | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | ||||||||||
| delta[x] | 0 | 0 | 0 | 1 | 0 | 1 | 2 | 2 | 1 | ||||||||||
| delta[y] | 0 | 1 |
2 |
2 | 2 | 2 | 1 | 2 | 1 | ||||||||||
| delta[ty] | 0 | 2 | 1 | 2 | 2 | 0 | 2 | 1 | 1 |
仔细再想想,tx-x 、x-y、y-ty,是不是很像向量形式,于是便有了一般化的结论:来自北大discuss
tx ty
| |
x ~ y
对于集合里的任意两个元素x,y而言,它们之间必定存在着某种联系,
因为并查集中的元素均是有联系的,否则也不会被合并到当前集合中。那么我们
就把这2个元素之间的关系量转化为一个偏移量,以食物链的关系而言,不妨假设
x->y 偏移量0时 x和y同类
x->y 偏移量1时 x吃y
x->y 偏移量2时 x被y吃,也就是y吃x
有了这些基础,我们就可以在并查集中完成任意两个元素之间的关系转换了。
不妨继续假设,x的当前集合根节点tx,y的当前集合根节点ty,x->y的偏移值为d-1(题中给出的询问已知条件)
(1)如果tx和ty不相同,那么我们把ty合并到tx上,并且更新deltx[ty]值(注意:deltx[i]表示i的当前集合根节点到i的偏移量!!!!)
此时 tx->ty = tx->x + x->y + y->ty,可能这一步就是所谓向量思维模式吧
上式进一步转化为:tx->ty = (deltx[x]+d-1+3-deltx[y])%3 = deltx[ty],(模3是保证偏移量取值始终在[0,2]间)
(2)如果tx和ty相同,那么我们就验证x->y之间的偏移量是否与题中给出的d-1一致
此时 x->y = x->tx + tx->y = x->tx + ty->y,
上式进一步转化为:x->y = (3-deltx[x]+deltx[y])%3,
若一致则为真,否则为假。
牛的想法啊!
凡人就模仿着学习啦~哈哈
接下来把这个想法再运用到路径压缩中:
ffx
| \
fx \
| /
| /
x
路径压缩过程中会将fx的父亲变为x的父亲,所以要改变相对关系,即偏移量。
ffx->fx+fx->x=ffx->x;
转换成:delta[x]=(delta[fx]+delta[x])%3;
下面是个人理解
这道题目的大概意思是先用t[]来存下两个动物之间的关系,0代表x和y是同类,1代表x吃y,2代表x被y吃
题目输入的是1,2,所以加入join时要type-1,大的else是用来跟新t[ty]的
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int pre[],t[],n;
int find(int x)
{
if(x==pre[x])
return x;
int tx=find(pre[x]);
t[x]=(t[x]+t[pre[x]])%;//关键,跟新路径
return pre[x]=tx;
}
int join(int x,int y,int type)
{
if(x>n||y>n)
return ;
if(type==&&x==y)
return ;
int tx=find(x);
int ty=find(y);
if(tx==ty)
{
if((t[y]-t[x]+)%!=type)
return ;
else return ;
}
else
{
pre[ty]=tx;
t[ty]=(t[x]-t[y]+type+)%;//关键,加3为了防止负数的出现!!!
return ;
}
}
int main()
{
int type;
int num,x,y,k;
while(~scanf("%d%d",&n,&k))
{
num = ;
for(int i=;i<=n;i++)
{
pre[i] = i;
t[i] = ;
}
while(k--)
{
scanf("%d%d%d",&type,&x,&y);
if(join(x,y,type-))
num++;
}
printf("%d\n",num);
}
return ;
}
POJ 1182 食物链(经典并查集) (多组输入有时乱加也会错!)的更多相关文章
- POJ 1182 食物链 经典并查集+关系向量简单介绍
题目: 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有 ...
- poj 1182 食物链 (并查集)
http://poj.org/problem?id=1182 关于并查集 很好的一道题,开始也看了一直没懂.这次是因为<挑战程序设计竞赛>书上有讲解看了几遍终于懂了.是一种很好的思路,跟网 ...
- POJ 1182 食物链(并查集拆点)
[题目链接] http://poj.org/problem?id=1182 [题目大意] 草原上有三种物种,分别为A,B,C A吃B,B吃C,C吃A. 1 x y表示x和y是同类,2 x y表示x吃y ...
- POJ 1182 食物链(并查集+偏移向量)题解
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 82346 Accepted: 24616 Description ...
- POJ 1182 食物链 (并查集解法)(详细注释)
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 78510 Accepted: 23396 Description ...
- POJ 1182 食物链(种类并查集)
记得第一次做这道题的时候,推关系感觉有点复杂,而且写完代码后一直WA,始终找不出错误. 在A了十几道并查集后,再做这道题,发现太小儿科了.发现原来之所以WA,就在于查找根节点时,没有同步更新子节点相对 ...
- 【POJ 1182 食物链】并查集
此题按照<挑战程序设计竞赛(第2版)>P89的解法,不容易想到,但想清楚了代码还是比较直观的. 并查集模板(包含了记录高度的rank数组和查询时状态压缩) *; int par[MAX_N ...
- POJ 1182 食物链 【并查集】
解题思路:首先是没有思路的----然后看了几篇解题报告 http://blog.csdn.net/ditian1027/article/details/20804911 http://poj.org/ ...
- poj 1182食物链(并查集)
算法思路:把那些确定了相对关系的节点放在同一棵树里(可以同时存在多棵树,单独每棵树中节点的相对关系确定),每个节点对应的 v[] 值记录他与根节点的关系( 0:同类: 1:根吃他: 2:他吃根 ).当 ...
随机推荐
- iOS程序员 如何提升核心竞争力,防止自己被裁员?
前言: 核心竞争力最早由普拉哈拉德和加里·哈默尔两位教授提出,通常认为核心竞争力,即企业或个人相较于竞争对手而言所具备的竞争优势与核心能力差异, 说白了就是你的优势,而且最好是独一无二的的优势,这就是 ...
- CentOS系统故障 | 一桩"血案"引发的容器存储驱动比较
写在前面: 由于红帽在Linux界的影响力,相信很多朋友在测试和生产系统用的是RedHat或者CentOS系统,这次我在CentOS系统上遇到了一个很有意思的故障,通过这次故障的原因分析及解决,特意写 ...
- 算法与数据结构基础 - 链表(Linked List)
链表基础 链表(Linked List)相比数组(Array),物理存储上非连续.不支持O(1)时间按索引存取:但链表也有其优点,灵活的内存管理.允许在链表任意位置上插入和删除节点.单向链表结构一般如 ...
- .net持续集成测试篇之Nunit参数化测试
系列目录 在进行单元测试的时候,很多时候,很多时候我们都是在单元测试方法内部提供特定的值,但是这样测试往往造成样本数不足从而导致覆盖的结果不够全面,很多时候我们更想提供来自外部的,满足条件的一组值来进 ...
- Visual Studio Debug
在watch窗口输入,$err,hr可以看到上一个错误代码和相关描述信息 Error Lookup可以将错误代码转换成为相应的文本描述 FormatMessage()
- FLV协议5分钟入门浅析
FLV协议简介 FLV(Flash Video)是一种流媒体格式,因其体积小.协议相对简单,很快便流行开来,并得到广泛的支持. 常见的HTTP-FLV直播协议,就是使用HTTP流式传输通过FLV封装的 ...
- Web开发中的相对路径和绝对路径
在学习HTML的时候一定会遇到引入文件和链接跳转页面,比如:JS文件.CSS文件.Image图片.我们就会考虑是相对路径和绝对路径的问题.下面PHP程序员雷雪松就详细讲解下Web开发中的相对路径和绝对 ...
- 使用Qt5+CMake实现图片的区域选择(附源码)
近期研发涉及到了图片的区域选择,找来一些资料一直不能很满意,所以自己实现了一个. 实现步骤如下.源码可以点击ImageAOI获取. 如下资料来自源码的README. ImageAOI (XLabel) ...
- 容易上手搭建vue2.0开发环境
第一步:安装node 前端开发框架和环境都是需要 Node.js ,先安装node.js开发环境,vue的运行是要依赖于node的npm的管理工具来实现,下载https://nodejs.org/en ...
- (三十)c#Winform自定义控件-文本框(三)
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...