题目链接http://poj.org/problem?id=1182

食物链
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 90077   Accepted: 27059

Description

动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形。A吃B, B吃C,C吃A。
现有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

第一行是两个整数N和K,以一个空格分隔。

以下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
解题思路:题解来源于挑战程序设计,对于每只动物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。因此对于每一条信息,只需按照如下进行操作就可以了。
第一种:x和y属于同一类,合并x-A和y-A,x-B和y-B,x-C和y-C。
第二种:x吃y 合并x-A和y-B,x-B和y-C,x-C和y-A。 不过在合并前,需要先判断合并是否会产生矛盾。例如在第一种情况下,需要先检查比如x-A和y-B或者y-C是否在同一组等信息。
附上代码:
 #include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=;
int n,k;
int par[maxn]; //父亲
int rank[maxn]; //树的高度 //初始化n个元素
void init(int n)
{
for(int i=;i<n;i++)
{
par[i]=i;
rank[i]=;
}
}
//查询树的根
int find(int x)
{
if(par[x]==x)
return x;
else
return par[x]=find(par[x]);
}
//合并x和y所属的集合
void unite(int x,int y)
{
if(find(x)==find(y))
return;
else
{
if(rank[find(x)]<rank[find(y)])
par[find(x)]=find(y);
else
{
par[find(y)]=find(x);
if(rank[find(x)]==rank[find(y)])
rank[find(x)]++;
}
}
}
//判断x和y是否在同一个集合
bool same(int x,int y)
{
return find(x)==find(y);
} int main()
{
scanf("%d%d",&n,&k);
//初始化并查集
//元素x,x+n,x+2*n分别为x-A,x-B,x-C
init(n*); int ans=;
for(int i=;i<k;i++)
{
int t,x,y;
scanf("%d%d%d",&t,&x,&y);
x-=,y-=; //把输入变成0~n-1的范围
//编号非法直接跳过
if(x<||x>=n||y<||y>=n)
{
ans++;
continue;
}
if(t==) //x和y属于同一类
{
if(same(x,y+n)||same(x,y+*n))
ans++;
else
{
unite(x,y);
unite(x+n,y+n);
unite(x+n*,y+n*);
}
}
else //x吃y
{
if(same(x,y)||same(x,y+*n))
ans++;
else
{
unite(x,y+n);
unite(x+n,y+*n);
unite(x+*n,y);
}
}
}
printf("%d\n",ans);
return ;
}

相似题:hdu1829 A Bug's Life

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=1829

题目大意::给你n个虫,输入m行a,b,表示a和b是异性,要你判断是否有同性恋

解题思路:类型基本一致,比那个更简单,情况就两种,同性和异性,建立两个集合就行,如果输入的a、b同时存在一个集合当中,说明他们就是同性恋了。

附上代码:

 #include<stdio.h>
int par[],rank[]; void init(int x)
{
for(int i=;i<=x;i++)
{
par[i]=i;
rank[i]=;
}
} int find(int x)
{
if(x==par[x])
return x;
else
return par[x]=find(par[x]);
} void unite(int x,int y)
{
int rootx=find(x);
int rooty=find(y);
if(x==y)
return;
if(rank[rootx]<rank[rooty])
par[rootx]=rooty;
else
{
par[rooty]=rootx;
if(rank[rootx]==rank[rooty])
rank[rootx]++;
}
} bool same(int x,int y)
{
return find(x)==find(y);
} int main()
{
int t;
scanf("%d",&t);
int kase=;
while(t--)
{
int n,m;
int flag=;
scanf("%d%d",&n,&m);
init(n*);
while(m--)
{
int a,b;
scanf("%d%d",&a,&b);
unite(a,b+n);
unite(a+n,b);
if(same(a,b)||same(a+n,b+n))
flag=;
}
printf("Scenario #%d:\n",kase++);
if(flag)
printf("Suspicious bugs found!\n");
else
printf("No suspicious bugs found!\n");
printf("\n");
}
return ;
}

poj1182、hdu1829(并查集)的更多相关文章

  1. POJ-1182 食物链---并查集(附模板)

    题目链接: https://vjudge.net/problem/POJ-1182 题目大意: 中文题,不多说. 思路: 给每个动物创建3个元素,i-A, i-B, i-C i-x表示i属于种类x,并 ...

  2. POJ-1182 食物链 并查集(互相关联的并查集写法)

    题目链接:https://cn.vjudge.net/problem/POJ-1182 题意 中文题目,就不写了哈哈 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃 ...

  3. *HDU1829 并查集

    A Bug's Life Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  4. [poj1182]食物链(并查集+补集)

    食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 64841   Accepted: 19077 Description ...

  5. POJ-1182 分组并查集

    今天刚发现,之前做的并查集只是贴模板基本就能过,题意改变一点,自己还是不懂,其实我还没入门呢... 题意:食物链,A吃B,B吃C,C吃A,输入m组数据: 1 a b:a 和 b 是同一类 2 a b: ...

  6. poj1182食物链--并查集

    动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种.有人用两种说 ...

  7. poj1182(并查集)

    题目链接 分析:根据分析,关系的递推满足由[a,b]~[b,c]得:[a,c]=([a,b]+[b,c])%3;[a,d]=([a,b]+[b,c]+[c,d])%3.由rank数组表示关系 0 -  ...

  8. 食物链--poj1182(并查集含有关系)

    http://poj.org/problem?id=1182   题意应该就不用说了  再次回到食物链这道题,自己写了一遍,一直wa...原因竟然是不能用多实例,我也是醉了,但是我真的彻底的理解了,那 ...

  9. POJ1182 食物链 并查集

    #include<iostream>#include<stdio.h>#include<string.h>using namespace std;const int ...

  10. POJ1182 食物链---(经典种类并查集)

    题目链接:http://poj.org/problem?id=1182   食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submission ...

随机推荐

  1. SQL性能优化-order by语句的优化

    原文:http://bbs.landingbj.com/t-0-243203-1.html 在某些情况中,MySQL可以使用一个索引来满足ORDER BY子句,而不需要额外的排序.where条件和or ...

  2. 1px实现方案

    JS处理 首先,可以通过 window.devicePixelRatio 拿到设备的像素比,然后给 html 标签加上的相应的样式. function retina () { // 高分辨率屏幕处理 ...

  3. python学习笔记(4)-基本数据类型-数字类型及操作

    大学mooc 北京理工大学 python语言程序设计课程学习笔记 一.整数类型 可正可负,没有取值范围的限制(这个与c不同,c要考虑数据类型的存储空间).如pow(x,y),计算x的y次方,pow(2 ...

  4. 关于对ProgressBar定义模板的一些总结

    在之前的博客中曾经写到了一篇关于如何定义圆形进度条的文章,今天就ProgressBar再来进行一些总结,首先来介绍一下ProgressBar的结构,ProgressBar控件的模板有两个部分,我们在定 ...

  5. Chromecast

    Chromecast chrome://cast/#offers https://chromecast.com/help https://www.pcmag.com/feature/326584/24 ...

  6. Java多线程2:线程的使用及其生命周期

    一.线程的使用方式 1.继承Thread类,重写父类的run()方法 优点:实现简单,只需实例化继承类的实例,即可使用线程 缺点:扩展性不足,Java是单继承的语言,如果一个类已经继承了其他类,就无法 ...

  7. replace只能输入小数

    case "checkPrice": tr.find(".layui-table-edit").keyup(function () { var $input = ...

  8. 【Python练习题】程序5

    #题目:输入三个整数x,y,z,请把这三个数由小到大输出. # a = input('请输入整数: \n') # # b = input('请输入整数: \n') # # c = input('请输入 ...

  9. Nginx 接受上游缓存流程

    L:101 这个指令主要是由上游服务器来决定是否缓存 详见博客Nginx 针对上游服务器缓存

  10. H.264编码原理以及I帧B帧P帧

    前言 ----------------------- H264是新一代的编码标准,以高压缩高质量和支持多种网络的流媒体传输著称,在编码方面,我理解的他的理论依据是:参照一段时间内图像的统计结果表明,在 ...