POJ_1182_食物链
来源:互联网 发布:linux vsftpd pid 太多 编辑:程序博客网 时间:2024/05/17 23:50
食物链
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 53514 Accepted: 15677
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),输出假话的总数。
现有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。
以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。
若D=1,则表示X和Y是同类。
若D=2,则表示X吃Y。
Output
只有一个整数,表示假话的数目。
Sample Input
100 71 101 1 2 1 22 2 3 2 3 3 1 1 3 2 3 1 1 5 5
Sample Output
3
Source
Noi 01
带权并查集的经典问题
但是还没有理解带权并查集的思想
自己只能写出这种疯狂的集合关系的代码
三种动物于是开三个集合
#include <iostream>#include <stdio.h>using namespace std;const int M=5e4+5;int uf[M]; //本身的集合int eat[M]; //吃谁int beat[M]; //被谁吃int find(int i){ if(i==uf[i]) return i; return uf[i]=find(uf[i]);}void merge(int i,int j){ int t1=find(i); int t2=find(j); if(t1==t2) return; uf[t2]=t1; //合并i和j if(eat[t2]&&eat[t1]) //合并i和j的吃集 merge(eat[t2],eat[t1]); else if(eat[t1]) eat[t2]=find(eat[t1]); else eat[t1]=find(eat[t2]); if(beat[t2]&&beat[t1]) //合并i和j的被吃集 merge(beat[t2],beat[t1]); else if(beat[t1]) beat[t2]=find(beat[t1]); else beat[t1]=find(beat[t2]); //这一系列复杂判断也可以换一种方式} //给吃和被吃数组赋值一组根本不会出现的不同数值,如M+ivoid clear(int n) //初始化{ for(int i=0;i<=n;i++) { uf[i]=i; eat[i]=0; beat[i]=0; }}int main(){ int n,k; int lie; int con,a,b; //freopen("1.in","r",stdin); scanf("%d%d",&n,&k); lie=0; clear(n); for(int i=0;i<k;i++) { scanf("%d%d%d",&con,&a,&b); if(a>n||b>n) { lie++; continue; } int seta=find(a); //a所在集合 int setb=find(b); //b所在集合 int ae=find(eat[seta]); //a的吃集 int be=find(eat[setb]); //b的吃集 int abe=find(beat[seta]); //a的被吃集 int bbe=find(beat[setb]); //b的被吃集 if(con==1) //说两者是同种 { if(seta==setb) //确实同种 continue; if(ae==setb||abe==setb||be==seta||bbe==seta) //有被吃关系,假 { lie++; continue; } else { merge(seta,setb); //同种需合并 } } if(con==2) //a吃b { if(seta==setb) //a和b同种,假 { lie++; continue; } if(ae==setb&&bbe==seta) //a确实吃b continue; if(be==seta||abe==setb) //b吃a,假 { lie++; continue; } else //需要处理a吃b 则b与a的吃集合并 b的被吃集与a合并 { if(!eat[seta]) eat[seta]=setb; if(!beat[setb]) beat[setb]=seta; if(abe&&be) //如果a有被吃集b有吃集,则a的被吃集与b的吃集是同种 需要合并 merge(abe,be); else if(abe) eat[setb]=abe; else beat[seta]=be; merge(eat[seta],setb); merge(beat[setb],seta); } } //for(int i=1;i<=8;i++) // cout<<i<<" "<<uf[i]<<" "<<eat[i]<<" "<<beat[i]<<endl; //cout<<endl; } printf("%d\n",lie); return 0;}
0 0
- POJ_1182_食物链
- POJ_1182_食物链
- poj_1182_食物链(并查集)
- poj_1182_并查集
- 食物链
- 食物链
- 食物链
- 食物链
- 食物链
- 食物链
- 食物链
- 食物链
- 食物链
- 食物链
- 食物链
- 食物链
- 食物链
- 食物链
- Python 实现一个简单的http服务器
- 应用层
- hudson--环境变量
- HDOJ 1879 继续畅通工程 最小生成树 kruskal && prim
- hdu1233还是畅通工程【最小生成树】
- POJ_1182_食物链
- iAngularGaugeX--角形刻度尺控件的使用【图文】
- spring quartz定时
- tomcat6.0 安装版和解压版的内存设置
- Java中getBytes()的用法
- 【Rochchip 定制】添加自动重启功能
- Python post中文参数传递出错的一种解决办法
- HDU 1556 Color the ball(线段树)
- Ceil函数