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 偏移量 ...
随机推荐
- 利用Powershell和ceye.io实现Windows账户密码回传
利用Powershell和ceye.io实现Windows账户密码回传 转自:http://www.freebuf.com/articles/system/129068.html 最近在研究Power ...
- position记录元素原始位置
position记录元素原始位置 css样式: li { width: 100px; height: 100px; margin: 10px 0 0 10px; background-color: # ...
- Scrapy日志等级以及请求传参
日志等级 请求传参 提高scrapy的爬取效率 日志等级 - 日志信息: 使用命令:scrapy crawl 爬虫文件 运行程序时,在终端输出的就是日志信息: - 日志信息的种类: - ERROR ...
- ansible upload
# 链接地址:https://www.cnblogs.com/xiaoxiaoleo/p/6626299.html # synchronize: 从拉取远程服务器文件,需要加mode: pull # ...
- C#中DataSet中的relation
//关系定义的方法是 DataRelation 变量名 = “DataSet对象”.Relations.Add("关系名",DataSet对象.主表.列名 , DataSet对象. ...
- Java基础1一环境配置
1.下载JDK:http://www.oracle.com/technetwork/java/javase/downloads/index.html 2.JDK安装:直接点击下一步,直到完成.注:默认 ...
- wpf 错误 执行了 QueryInterface 调用,请求提供 COM 可见的托管类“BoilerMonitoringV1._0.MapControl”的默认 IDispatch 接口。
在做wpf嵌入地图时,在自定义的WebBrowser 里面使用JavaScript调用外部方法的时报的错误 在原来的WinForm里 我们只要在窗体类设置的头部设置个 [System.Runtime. ...
- 用Navicat自动备份mysql数据库
以下文章转载自https://blog.csdn.net/u013628152/article/details/54909885,放在自己的博客园以供后面方便查询 —————————————————— ...
- 【Oracle】闪回技术
1.闪回技术描述 2.数据库的准备: --undo表空间要设置成AUTO,设置合适的保存时间.undo表空间: SYS@ENMOEDU> show parameter undo NAME TYP ...
- 知识工程.Vs.软件构架,框架,设计模式.
软件工程-原文链接:http://tech.it168.com/a2009/0902/672/000000672853.shtml 此文章详细给出了软件设计的基本概念和用途,文章链接:http://w ...