POJ1182 食物链 解题报告
来源:互联网 发布:传智播客java全套视频 编辑:程序博客网 时间:2024/05/16 11:28
动物王国中有三类动物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和K句话,输出假话的总数。
【输入格式】
第一行是两个整数N和K,以一个空格分隔。
以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。
若D=1,则表示X和Y是同类。
若D=2,则表示X吃Y。
【输出格式】
只有一个整数,表示假话的数目。
【输入样例】
100 7
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5
【输出样例】
3
【数据范围】
1<=N<=50,000
0<=K<=100,000
【来源】
对输入的7句话的分析如下:
100 7
1 101 1 假话
2 1 2 真话
2 2 3 真话
2 3 3 假话
1 1 3 假话
2 3 1 真话
1 5 5 真话
解题思路:根据题意,可以运用并查集的思想来解决此题,对于每次输入的话,先判断输入的X与Y的关系是否已知,如果未知,则将X与Y存入并查集中,并注明X与Y的关系;如果已知,则判断已知关系与所输入的关系是否相同(注意,如果X>N或Y>N,则输入的话是假话)。本题的重点及难点在于,已知X的关系和Y的关系,如何将他们的关系合并,要具体情况具体分析,下面就本题出现的合并关系的情况一一进行分析。先设pa[i]==j(i的父亲是j),re[i]==0表示i与j是同类,re[i]==1表示i被j吃,re[i]==2表示i吃j。
①在寻找x所在集合的代表元(根),进行路径压缩时,将x的关系与pa[x](x的父亲)的关系进行合并。
通过上图,可以看出当x被pa[x]吃,而pa[x]吃root(根)时,x与root同类。同理,多列举几种可能,可以得出此时的关系合并的通式为re[x]=(re[x]+re[pa[x]])%3。
②在通过输入数据确定了x与y的关系后,将x的根与y的根(路径压缩后,即为他们的父亲)的关系进行合并。
通过上图,可以看出若输入的话为x吃y(y被x吃),而假设y与py是同类,x吃px,则px与py是同类。同理,多列举几种可能,设合并时py的父亲改为px,可以得出通式为re[py]=(re[x]-re[y]+d+3)%3(这里的d为根据输入得出的y对于x的关系)。
③在输入每句话,判断X与Y的关系是否已知,如果X与Y的关系未知(X与Y的根不同),则返回3,如果已知关系,则返回已知的Y与X的关系。(px、py分别为x和y的根,路径压缩后即为他们的父亲)(注,这里返回的是Y对于X的关系)
通过上图,可以看出若y被py吃,x吃px,y吃x。同理,多列举几种可能,可以得出通式返回的值为(re[y]-re[x]+3)%3。
#include<cstdio>#include<cstdlib>#include<iostream>#include<algorithm>#include<cstring>#include<queue>#include<vector>#include<cmath>using namespace std;const int maxn=50005;int N,K,d,x,y,ans=0;int pa[maxn],re[maxn]; //设pa[i]==j(i的父亲是j),re[i]==0表示i与j是同类,re[i]==1表示i被j吃,re[i]==2表示i吃jvoid initial() //并查集初始化{for(int i=1;i<=N;i++)pa[i]=i,re[i]=0;}int find(int x){if(pa[x]==x) return x;int root=find(pa[x]);re[x]=(re[x]+re[pa[x]])%3; //重点pa[x]=root;return root;}int judge(int x,int y) //0同类 1被吃 2吃 3不知道{int px=find(x);int py=find(y);if(px!=py) return 3; return (re[y]-re[x]+3)%3; //重点,难点,返回的是y对于x的关系}void bing(int x,int y,int d) //这里的d为y对于x的关系{int px=find(x);int py=find(y);pa[py]=px;re[py]=(re[x]-re[y]+d+3)%3; //重点,难点}int main(){//freopen("48.in","r",stdin);//freopen("48.out","w",stdout);scanf("%d%d",&N,&K);initial();for(int i=1;i<=K;i++){scanf("%d%d%d",&d,&x,&y);int t=judge(x,y);if(x>N || y>N) {ans++;continue;}if(t==3) //关系未知{bing(x,y,d-1);continue;}if(t!=d-1) ans++; //因为返回的是y对于x的关系,这里才可以用t!=d-1来判断}printf("%d\n",ans);return 0;}
- POJ1182 食物链 解题报告
- poj1182解题报告
- POJ1182 解题报告
- 【POJ1182】食物链,思路+数据+代码,可能是史上关于这道题最详细的解题报告
- POJ1182 食物链 ACM解题报告(并查集+路径压缩难题)
- POJ1182 食物链
- POJ1182食物链
- poj1182 食物链
- POJ1182--食物链
- poj1182-食物链
- poj1182 食物链
- poj1182 食物链
- POJ1182食物链
- poj1182 食物链
- POJ1182食物链
- POJ1182食物链
- POJ1182 食物链
- POJ1182:食物链
- FrameLayout《第一行代码Android》学习笔记
- angularJS之ui-router
- 适合狠新手看的java基本概念
- 64位下的相对指令地址
- 05Dockerfile简介
- POJ1182 食物链 解题报告
- java基础之数组
- 嵌入式Linux内核的制作
- ubuntu 安装 flashplugin-installer
- java基础之抽象类和接口
- Ubuntu 搭建 Shadowsocks
- Android Notification例子
- 7.17
- JavaScript高级特性 — 作用域