poj1182(食物链)
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 49320 | Accepted: 14385 |
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
建议:做此题之前先做 poj 2524 和 poj 1611。这两道题都是并查集的基础应用。
关键词:并查集 相对关系
思路:(用一个并查集就够了,同时对每个节点保持其到根结点的相对类别偏移量)
1.father[x]表示x的根结点。rank[x]表示father[x]与x的关系。rank[x] == 0 表示father[x]与x同类;1表示father[x]吃x;2表示x吃father[x]。
2.怎样划分一个集合呢?
注意,这里不是根据x与father[x]是否是同类来划分。而是根据“x与father[x]能否确定两者之间的关系”来划分,若能确定x与father[x]的关系,则它们同属一个集合。
3.怎样判断一句话是不是假话?
假设已读入 D , X , Y , 先利用find_set()函数得到X , Y 所在集合的代表元素 xf ,yf ,若它们在同一集合(即 xf == yf )则可以判断这句话的真伪( 据 2. ).
若 D == 1 而 rank[X] != rank[Y] 则此话为假。(D == 1 表示X与Y为同类,而从rank[X] != rank[Y]可以推出 X 与 Y 不同类。矛盾。)
若 D == 2 而 rank[X] == rank[Y] (X 与Y为同类)或者 rank[X] == ( rank[Y] + 1 ) % 3 (Y吃X )则此话为假。
4.上个问题中 r[X] == ( r[Y] + 1 ) % 3这个式子怎样推来?假设有Y吃X,那么r[X]和r[Y]的值是怎样的?
我们来列举一下: r[X] = 0 && r[Y] = 2
r[X] = 1 && r[Y] = 0
r[X] = 2 && r[Y] = 1
稍微观察一下就知道r[X] = ( r[Y] + 1 ) % 3;事实上,对于上个问题有更一般的判断方法:
若 ( r[Y] - r[X] + 3 ) % 3 != D - 1 ,则此话为假。(来自poj 1182中的Discuss )
5、注意事项:
A、我们用x--r-->y表示x和y之间的关系是r,比如x--1--y代表x吃y。现在,若已知x--r1-->y,y--r2-->z,如何求x--?-->z?,于是我们不难发现,x--(r1+r2)%3-->z。这个就是在Find_Set(int x)函数中用到的更新x与father[X]的关系
B、当D X Y时,则应合并X的根节点和Y的根节点,同时修改各自的rank。那么问题来了,合并了之后,被合并的根节点的kind值如何变化呢?
现有x和y,d为x和y的关系,xf和yf分别是x和y的根节点,于是我们有x--rank[x]-->xf,y--rank[y]-->yf,显然我们可以得到xf--(3-rank[x])-->x,yf--(3-rank[y])-->y。假如合并后x为新的树的根节点,那么原先fx树上的节点不需变化,yf树则需改变了,因为rank值为该节点和树根的关系。这里只改变rank(yf)即可,因为在进行find_set操作时可相应改变yf树的所有节点的kind值。于是问题变成了yf--?-->xf。我们不难发现yf--(3-rank[y])-->y--(3-d)-->x--rank[x]-->xf,根据前面的结论,我们有yf--(3-rank[y])-->y--(3-d)-->x--rank[x]-->xf。我们求解了xf和yf的关系了。
代码如下:
- #include <iostream>
- const int MAX=50005;
- int father[MAX];
- int rank[MAX];
- //初始化集合
- void Make_Sent(int x)
- {
- father[x]=x;
- rank[x]=0;
- }
- //查找x的集合,回溯时压缩路径,并修改x与father[x]的关系
- int Find_set(int x)
- {
- int t;
- if(x!=father[x])
- {
- t = father[x];
- father[x]= Find_set(father[x]);
- //更新x与father[X]的关系
- rank[x] = (rank[x]+rank[t])%3;
- }
- return father[x];
- }
- //合并x,y所在的集合
- void Union(int x,int y,int d)
- {
- int xf = Find_set(x);
- int yf = Find_set(y);
- //将集合xf合并到yf集合上
- father[xf] = yf;
- //更新 xf 与father[xf]的关系
- rank[xf]=(rank[y]-rank[x]+3+d)%3;
- }
- int main()
- {
- int totle=0;
- int i,n,k,x,y,d,xf,yf;
- scanf("%d%d",&n,&k);
- for(i=1;i<=n;++i)
- Make_Sent(i);
- while(k--)
- {
- scanf("%d%d%d",&d,&x,&y);
- //如果x或y比n大,或x吃x,是假话
- if(x>n||y>n||(d==2 && x == y))
- {
- totle++;
- }
- else
- {
- xf = Find_set(x);
- yf = Find_set(y);
- //如果x,f的父节点相同 ,那么可以判断给出的关系是否正确的
- if(xf == yf)
- {
- if((rank[x]-rank[y]+3)%3 != d-1)
- totle++;
- }
- else
- {
- //否则合并x,y
- Union(x,y,d-1);
- }
- }
- }
- printf("%d\n",totle);
- system("pause");
- return 0;
- }
poj1182(食物链)的更多相关文章
- 并查集专辑 (poj1182食物链,hdu3038, poj1733, poj1984, zoj3261)
并查集专题训练地址,注册登录了才能看到题目 并查集是一个树形的数据结构, 可以用来处理集合的问题, 也可以用来维护动态连通性,或者元素之间关系的传递(关系必须具有传递性才能有并查集来维护,因为并查集 ...
- POJ1182 食物链---(经典种类并查集)
题目链接:http://poj.org/problem?id=1182 食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submission ...
- NOI2001|POJ1182食物链[种类并查集 向量]
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 65430 Accepted: 19283 Description ...
- POJ-1182 食物链 并查集(互相关联的并查集写法)
题目链接:https://cn.vjudge.net/problem/POJ-1182 题意 中文题目,就不写了哈哈 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃 ...
- poj1182食物链_并查集_挑战程序设计竞赛例题
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 65534 Accepted: 19321 Description ...
- [poj1182]食物链(并查集+补集)
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 64841 Accepted: 19077 Description ...
- poj1182(食物链)续
意 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用 ...
- POJ1182 食物链(并查集)
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 55260 Accepted: 16210 Description ...
- (转)poj1182食物链
这题主要是看了http://blog.csdn.net/c0de4fun/article/details/7318642这篇解题报告,所以内容基本是转的!感谢大牛这么详细的把过程写的很清楚! 这道题目 ...
随机推荐
- ACL权限的学习
ACL ACL:访问控制列表,其主要作用是将一些"用户"加到表中,并对这些用户的行为进行控制. 案例: 有个文件夹project是root用户创建,并且关于这个文件夹有以下权限 d ...
- Javascript基础系列之(三)数据类型 (布尔型 Boolean)
javascript同样有布尔型,可选值,true or fasle. var marr = true ; document.write(typeof(marr) + "<br> ...
- Java Web技术总结(目录)
来源于:http://www.jianshu.com/p/539bdb7d6cfa Java Web技术经验总结(一) Java Web技术经验总结(二) Java Web技术经验总结(三) Java ...
- hdu4287 字典树
#include<stdio.h> #include<string.h> #include<stdlib.h> #define maxn 10 struct tri ...
- Java基础-四要素之一《抽象》(接口)
抽象的概念就是抽象出共同属性:成员变量和方法 定义抽象使用abstract关键字定义抽象类和方法 抽象类 abstract class 包含抽象方法的类,叫抽象类. 所以抽象类可以有private等多 ...
- 【poj2724】 Purifying Machine
http://poj.org/problem?id=2724 (题目链接) 题意 Mike有一个机器可以帮助他清理奶酪,每个奶酪由一个n位二进制数表示,机器上一共有n个按钮,每个按钮有1,0,*,其中 ...
- maven运行javaWeb项目
首先从svn下载下来的maven项目,需要点击项目,然后import--->Existing Maven Projects->全选之后点next就转换成功了,然后 run as--> ...
- (原)String类两种实例化的区别
String有两种实例化方式,一种是通过直接赋值的方式,另外一种是使用标准的new调用构造方法完成实例化. public class StringDemo { public static void m ...
- HDU 2242 考研路茫茫----空调教室
传送门 考研路茫茫——空调教室 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- 自动打包iOS项目
基于Lexrus的博文iOS-makefile,本文对自动打包涉及到的操作步骤以及理论基础进行了适当的补充. 请在阅读本文前先阅读<iOS makefile>.文章地址:http: ...