poj 1182 食物链 && nyoj 207(种类并查集)
| Time Limit: 1000MS | Memory Limit: 10000K | |
| Total Submissions: 52414 | Accepted: 15346 |
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
题意为:有A、B、C三种动物。A吃B,B吃C,C吃A,并给出一些条件,推断为你提供信息的人说了多少句假话。
并查集。通经常使用来检查两个元素是否在同一集合中,或者是将两个不同的集合为一个集合。
至于这道题。有神人曰。利用并查集,同一时候对每一个节点保持其到根结点的相对类别偏移量,定义为:
0——同类;
1——食物;
2——天敌。
一个非常具体的解题报告,看得我五体投地:点击打开链接
这里他讲的异常具体,哪一点都有讲到,,当中60行到180行就有下边凝视的公式的解析
好厉害。,2015,7,27
#include<stdio.h>
#define M 50005
int x[M],re[M];
void init()
{
for(int i=0;i<M;i++){
x[i]=i; re[i]=0;
}
}
int find(int k)
{
int temp=x[k];
if(x[k]==k) return k;
x[k]=find(x[k]);
re[k]=(re[k]+re[temp])%3;//( 儿子的关系 + 父亲的关系 ) % 3 = 儿子对爷爷的关系
return x[k];
}
void merge(int a,int b,int fa,int fb,int d)
{
x[fa]=fb;
re[fa]=(re[b]-re[a]+d+3)%3;//d是a与b的关系,(3-re[a])是a为根节点时,他父亲的关系,(re[b]-re[a]+d+3)%3就是a的根节点与他的父亲就是b的根节点的关系
}
int main()
{
int n,m,a,b,d,fa,fb,count=0;
scanf("%d%d",&n,&m);
init();
while(m--){
scanf("%d%d%d",&d,&a,&b);
if( a>n || b>n || (a==b && d==2) ){
count++;
continue;
}
fa=find(a);
fb=find(b);
if(fa==fb&&(re[a]-re[b]+3)%3!=d-1)//3-re[b]就得到了根节点和b的关系,re[a]+3-re[b]就是a关于b的关系
count++;
else
merge(a,b,fa,fb,d-1);
}
printf("%d\n",count);
return 0;
}
还有第二种比較巧妙的简单的方法:
对于每仅仅动物i创建3个元素i-A, i-B, i-C, 并用这3*N个元素建立并查集。这个并查集维护例如以下信息:
① i-x 表示 “i属于种类x”。
②并查集里的每个组表示组内全部元素代表的情况都同一时候发生或不发生。
比如,假设i-A和j-B在同一个组里,就表示假设i属于种类A那么j一定属于种类B,假设j属于种类B那么i一定属于种类A。
因此,对于每一条信息。仅仅须要依照以下进行操作就能够了。
1)第一种。x和y属于同一种类———合并x-A和y-A、x-B和y-B、x-C和y-C。
2)另外一种,x吃y—————————合并x-A和y-B、x-B和y-C、x-C和y-A。
只是在合并之前须要先推断合并是否会产生矛盾。比如在第一种信息的情况下,
须要检查比方x-A和y-B或者y-C是否在同一组等信息。
(一開始我一直不明确。对于两种信息都是合并,
那么以后怎么分清究竟是同类还是捕食关系呢,或者说怎样推断是否会产生矛盾呢?
后来发现,它利用3*N的数组分3段1~N,N~2N,2N~3N分别当做是A、B、C三个种类的集合,
把全部可能符合的情况都会导入进去。尽管对于两种信息的操作都是合并。
但合并的内容是不一样的,这样就能够在合并之前推断其是否以还有一种信息合并过或者符合还有一种信息。能够自己举例来理解一下)
#include<stdio.h>
#define M 50005*3
int x[M];
void init()
{
for(int i=0;i<M;++i){
x[i]=i;
}
}
int find(int k)
{
if(x[k]==k) return k;
x[k]=find(x[k]);
return x[k];
}
void merge(int a,int b)
{
int fa=find(a); int fb=find(b);
if(fa!=fb) x[fa]=fb;
}
bool same(int a,int b)
{
return find(a)==find(b);
}
int main()
{
int n,m,a,b,c,count=0;
scanf("%d%d",&n,&m);
init();
while(m--){
scanf("%d%d%d",&c,&a,&b);
//元素a。a+N,a+2*N分别代表a-A。a-B,a-C
if(a>n || b>n ||(a==b && c==2)) {
count++;
continue;
}
if(c==1){
if(same(a,b+n) || same(a,b+2*n))
count++;
//对于第一种信息是不能出现捕食与被捕食关系的
else{
merge(a,b);
merge(a+n,b+n);
merge(a+2*n,b+2*n);
}
}
else{
if(same(a,b) || same(a,b+2*n)) count++;
//不能出现捕食同类和反捕食的情况
else{
merge(a,b+n);
merge(a+n,b+2*n);
merge(a+2*n,b);
}
}
}
printf("%d\n",count);
return 0;
}
poj 1182 食物链 && nyoj 207(种类并查集)的更多相关文章
- poj 1182 食物链(高级的带权并查集)
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 76486 Accepted: 22742 Description ...
- 【POJ】2492 A bug's life ——种类并查集
A Bug's Life Time Limit: 10000MS Memory Limit: 65536K Total Submissions: 28211 Accepted: 9177 De ...
- hdu 1182 A Bug's Life(简单种类并查集)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1829 题意:就是给你m条关系a与b有性关系,问这些关系中是否有同性恋 这是一道简单的种类并查集,而且也 ...
- POJ 1703 Find them, Catch them(种类并查集)
Find them, Catch them Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 41463 Accepted: ...
- 种类并查集,Poj(1703)
题目链接:http://poj.org/problem?id=1703 第一次做种类并查集,有的地方还不是很清楚,想了一上午,有点明白了,这里记录一下. 这里我参考的红黑联盟的题解. 关键:种类并查集 ...
- POJ1703--Find them, Catch them(种类并查集)
Time Limit: 1000MSMemory Limit: 10000K Total Submissions: 32909Accepted: 10158 Description The polic ...
- poj 1182:食物链(种类并查集,食物链问题)
食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 44168 Accepted: 12878 Description ...
- poj 1182 食物链(种类并查集 ‘初心者’)
题目链接:http://poj.org/problem?id=1182 借着这题可以好好理解一下种类并查集,这题比较简单但挺经典的. 题意就不解释了,中问题. 关于种类并查集结局方法也是挺多的 1扩增 ...
- POJ 1182食物链(分集合以及加权两种解法) 种类并查集的经典
题目链接:http://icpc.njust.edu.cn/Problem/Pku/1182/ 题意:给出动物之间的关系,有几种询问方式,问是真话还是假话. 定义三种偏移关系: x->y 偏移量 ...
随机推荐
- poj 3259-- Wormholes(SPFA)
...
- 将python的程序包装成windows下的service
使用python编写的脚本应用程序,在运行的时候需要有python的运行环境,但是我们肯定是希望整个python程序能够像应用程序一样打包生成一个包括其运行环境的exe文件包,这是第一步,但是要想使用 ...
- 最详细的CentOS 6与7对比(二):服务管理对比
本主题将从3个角度进行对比 常见设置(CentOS 6 vs CentOS 7) 服务管理(Sysvinit vs Upstart vs Systemd) 性能测试(cpu/mem/io/oltp) ...
- AHOI 2009 (BZOJ1798)维护序列 seq (线段树好题?)
我是不会说这个题很坑的.. 改了一晚上... // by SiriusRen #include <cstdio> #define N 150000 #define LSON l,mid,l ...
- LeetCode Weekly Contest 20
1. 520. Detect Capital 题目描述的很清楚,直接写,注意:字符串长度为1的时候,大写和小写都是满足要求的,剩下的情况单独判断.还有:我感觉自己写的代码很丑,判断条件比较多,需要改进 ...
- DDL:对数据库___database___的相关操作,包含数据库备份,导入
1.创建数据库 create database mydb2; create database mydb2 character set utf8; 2.删除数据库 drop database mydb2 ...
- JS 经验总结
1.IE中div的高度是content+padding+border之和,其它的是content的高度 2.一个标签里面只有一个属性,class='cls1 cls2' 3.同一页面不能出现相同的id ...
- Super超级ERP系统---(7)货位管理
货位是ERP系统总的仓库管理中必不可少的,仓库是有货架组成,货架上的每个格子就是一个货位,所有货位上的商品的库存总和就是仓库商品的库存.仓库的货位主要分为货架和托盘,货架就是仓库的固定货位,托盘就是移 ...
- JavaScript数组的操作
<html> <head> <meta charset="utf-8"> <title>无标题文档</title> &l ...
- Static variables in JavaScript
function MyClass () { // constructor function var privateVariable = "foo"; //NO:obj.privat ...