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 偏移量 ...
随机推荐
- 05.使用jdk发布webservice服务
无论服务端是用什么写的,使用框架写的还是用jdk写的,它都会发布出来这样一个东西.主要你遵循咱们这七个步骤来走就可以调用了. 咱们现在转换一下角色,自己发布一个服务让别人去调.怎么来发布一个服务? 我 ...
- Reorder List 最典型的linkedlist题目
https://oj.leetcode.com/problems/reorder-list/ Given a singly linked list L: L0→L1→…→Ln-1→Ln,reorder ...
- php和nodejs
整个故事正如好莱坞大片的经典剧情走向:两位昔日好友如今分道扬镳,甚至被迫陷入了你死我活的斗争当中.刚开始的分歧并不严重,无非是一位老友对于另一位伙伴长久以来占据.但又绝口不提的业务领域产生了点兴趣.而 ...
- java8 Stream 笔记
stream的定义:对一个源中的一系列元素进行聚合操作. 一系列元素:stream对一组有特定类型的元素提供了一个接口.但是stream并不真正存储元素,元素根据需求被计算出来. 源:stream可以 ...
- BZOJ4832: [Lydsy1704月赛]抵制克苏恩(期望DP)
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 913 Solved: 363[Submit][Status][Discuss] Description ...
- JavaScript定时器的开启关闭
<html> <head> <meta charset="utf-8"> <title>无标题文档</title> &l ...
- angular实现的tab栏切换
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Android 自定义控件之圆形扩散View(DiffuseView)
实现效果 使用 属性方法 代码 源码下载 参考链接 实现效果 使用 XML中: <com.airsaid.diffuseview.widget.DiffuseView android:id=&q ...
- Android学习——利用RecyclerView编写聊天界面
1.待会儿会用到RecyclerView,首先在app/build.gradle(注意有两个build.gradle,选择app下的那个)当中添加依赖库,如下: dependencies { comp ...
- DevExpress 如何读取当前目录下文件,加载至grid
DBFileName=DevExpress.Utils.FileHelper.FindingFileName(Appliaction.StartupPath,"Data\\Product&g ...