POJ-1182 食物链
来源:互联网 发布:摇钱树网吧计费软件 编辑:程序博客网 时间:2024/05/22 06:11
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 71 101 1 2 1 22 2 3 2 3 3 1 1 3 2 3 1 1 5 5
Sample Output
3
Source
————————————————————午休的分割线————————————————————
前言:学习(关系)并查集不能不学的经典例题,在网上搜到很多一个比一个详细的题解。当然我自己的题解也相当费心了,转载请注明——出处:http://blog.csdn.net/j_sure/article/details/25884819
推荐三个网址:match7 Cfreezhan c0de4fun
思路:之前学习并查集的模板(参见:畅通工程),使用了路径压缩。但是对路径压缩的理解模模糊糊。这道题就是让你深刻理解路径压缩究竟是怎么一回事的。
看到很多人的题解报告一开始就说,设0、1、2分别对应着一种结点与其父亲之间的关系,然后给出了推导公式的过程。我个人觉得没有从问题的本质开始分析,难以看懂。让我们一起来分析一下。
首先,并查集是一种擅长处理集合之间合并与查询的树型数据结构。集合之间的合并,就意味着事物之间关系的改变。相当抽象也非常有趣。例如此题,ABC是三种动物,相互有着“吃”或“被吃”的关系,之后给出庞大数量的三种动物,找到这些动物之间符合逻辑的关系。
动机——
每当阐明一个动物与另一个动物之间的关系,即可先进行逻辑判断,之后根据需要来储存它们的“关系信息”并且纳入集合当中。
建立这种树型数据结构的时候,如果这棵树深度越来越大,甚至变成一条长链,那么查询耗费的时间是相当无法忍受的。因此我们在查询的同时,进行递归式的“路径压缩”。只有路径压缩才能让查询复杂度变成O(1)。
int Find(int x) { if(x != fath[x]) fath[x] = Find(fath[x]); return fath[x];}
上面的路径压缩,递归的边界是x的父亲是自己(祖先)。这是灵活的,因为我们在初始化的时候,每个结点的父亲都是自己,这时候每个结点“自成一个集合”。大概思考之后,发现每次查询都是查到祖先为止,之后返回祖先。但是仔细地思考一下,姑且假设存在一条长链,那么递归到边界(即查到祖先)之后,回溯的过程显然是在“改变父亲”。也就是说,每回溯一层,就会使该结点的父亲变成祖先。(这是在“压缩父亲”)
理解了路径压缩,自然而然会想到一个问题。并查集通过建立父子关系来储存数据,那么想要储存捕食关系也只能储存结点与其父亲之间的捕食关系,那么既然会改变父亲,而每个结点储存的与其父亲之间的捕食关系势必发生变化,那么路径压缩真的可行吗?暂时不考虑这个,先考虑如何通过输入储存结点信息。
储存关系——
抽象问题——
if(def == 1)tree[rt_y].relation = (tree[x].relation - tree[y].relation + 3) % 3;elsetree[rt_y].relation = (tree[x].relation - tree[y].relation + 1 + 3) % 3;根据def的特殊性,两个式子可以合并。但是我并不赞成这么做。
可行性——
int Find(int x){int tmp;if(x != tree[x].parent) {tmp = tree[x].parent;//暂存父亲tree[x].parent = Find(tmp);//压缩父亲tree[x].relation = ......;//修改关系}return tree[x].parent;}所修改的关系即——通过x和它父亲(tmp)的关系以及tmp和tmp的父亲的关系推出x和它爷爷(tmp的父亲)的关系,将x的父亲(tmp)压缩,修改成x的爷爷。(这么一来就压缩掉了一个父亲,同时修改了关系)推导的过程依然是找规律。
//压缩掉tmp之后,应修改tree[x].relation为x与爷爷的关系tree[x].relation = (tree[x].relation + tree[tmp].relation) % 3;
逻辑判断——
新姿势——
/*我的题解报告:http://blog.csdn.net/j_sure/article/details/25884819*/ #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> #include <stack> #include <queue> #include <vector> #include <map> #include <string> #include <iostream> using namespace std;/****************************************/const int N = 50010;const int r_sam[3][3] = {0, 2, 1, 1, 0, 2, 2, 1, 0}, r_eat[3][3] = {1, 0, 2, 2, 1, 0, 0, 2, 1};const int r_gra[3][3] = {0, 1, 2, 1, 2, 0, 2, 0, 1};int ans;struct Tree{int parent;char relation;}tree[N];int Find(int x){int tmp;if(x != tree[x].parent) {tmp = tree[x].parent;tree[x].parent = Find(tmp);tree[x].relation = r_gra[tree[x].relation][tree[tmp].relation];}return tree[x].parent;}void Union(int def, int x, int y){int rt_x = Find(x), rt_y = Find(y);if(rt_x != rt_y) {tree[rt_y].parent = rt_x;if(def == 1)tree[rt_y].relation = r_sam[tree[x].relation][tree[y].relation];elsetree[rt_y].relation = r_eat[tree[x].relation][tree[y].relation];return ;}if(def == 1 && tree[x].relation != tree[y].relation) {ans++;return ;}if(def == 2 && (tree[x].relation + 1) % 3 != tree[y].relation) {ans++;return ;}}int main(){int n, k;scanf("%d%d", &n, &k);ans = 0;for(int i = 1; i <= n; i++) {tree[i].parent = i;tree[i].relation = 0;}for(int i = 1; i <= k; i++) {int def, x, y;scanf("%d%d%d", &def, &x, &y);if(x > n || y > n) {ans++;continue;}if(def == 2 && x == y) {ans++;continue;}Union(def, x, y);}printf("%d\n", ans);return 0;}
- poj 1182 食物链
- poj 1182 食物链
- poj 1182 食物链(转)
- poj 1182 食物链
- poj 1182 食物链
- poj 1182 食物链
- POJ-1182 食物链
- POJ 1182 食物链
- poj 1182食物链
- POJ 1182 食物链
- POJ 1182 食物链
- poj 1182 食物链
- POJ 1182 食物链
- POJ 1182 食物链
- poj 1182 食物链
- POJ 1182 - 食物链
- poj 1182 食物链
- poj 1182 食物链
- 条形图
- 属性readwrite,readonly,assign,retain,copy,nonatomic
- (一)SVM的八股简介
- 处理标点符号
- Java中关于Volatile的那些事儿
- POJ-1182 食物链
- 计算机常用术语简写
- PL/SQL计算质数
- poj3295
- [Wikioi 1253]超级市场(疑难题)
- C语言开发之Hello,World来龙去脉
- 我开通博客了
- CString 与数字之间的转换
- 自己做的一个输入输出缓冲池