POJ1182食物链【并查集+根节点的偏移】

动物王国中有三类动物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

只有一个整数,表示假话的数目。

分析:这个题的思路跟上个题的思路一模一样,只是他的操作多加了一种叫做 x y是同类

其实这个很好处理的  只要在合并的是后其偏移关系设为0  那么就可以了

代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5
 6 const int maxn = 50005;
 7
 8 int fa[maxn], num[maxn];
 9
10 void init(int n) {
11     for(int i = 0; i <= n; i++) {
12         fa[i] = i;
13         num[i] = 0;
14     }
15 }
16
17 int find(int i) {
18     if(fa[i] == i) {
19         return i;
20     }
21     int fi = fa[i];
22     fa[i] = find(fa[i]);
23     num[i] = (num[i] + num[fi] + 6) % 3;
24     return fa[i];
25 }
26
27 void unin(int u, int v) {
28     int fu = find(u); int fv = find(v);
29     if(fu != fv) {
30         fa[fv] = fu;
31         num[fv] = (num[fv] + (num[u] + 1 - num[v]) + 6) % 3;
32     }
33 }
34
35 void unin2(int u, int v) {
36     int fu = find(u); int fv = find(v);
37     if(fu != fv) {
38         fa[fv] = fu;
39         num[fv] = (num[fv] + (num[u] - num[v]) + 6) % 3;
40     }
41 }
42
43 int main() {
44     int n, k;
45     int c, a, b;
46     scanf("%d %d",&n, &k);
47     int ans = 0;
48     init(n);
49     while(k--) {
50         scanf("%d %d %d",&c, &a, &b);
51
52         if(a > n || b > n) {
53             ans++;
54             continue;
55         }
56         if(c == 2 && a == b) {
57             ans++;
58             continue;
59         }
60         if(c == 1) {
61             if(find(a) == find(b) ) {
62                 if(num[a] != num[b]) {
63                     ans++;
64                 }
65             } else {
66                 unin2(a, b);
67             }
68         } else {
69             if(find(a) == find(b) ) {
70                 if(num[b] !=  ( num[a] + 1 ) % 3 ) {
71                     ans++;
72                 }
73             } else {
74                 unin(a, b);
75             }
76         }
77     }
78     printf("%d\n", ans);
79     return 0;
80 }

时间: 2024-12-12 09:58:10

POJ1182食物链【并查集+根节点的偏移】的相关文章

POJ2492A Bug&#39;s Life【并查集+根节点偏移】

大意: 告诉你一些关系 a b 代表 a 和 b 是异性 问这些关系中有没有错误的语句 分析: 有并查集维护其是否在同一个集合之中  在开一个num数组来维护对于根节点的偏移量 在find的时候只需要递归到根节点返回的过程中把num数组进行维护就可以了 在进行合并的时候我们需要考虑到把一个点的根节点并到另一个的根节点上 所以要根据u和v的偏移关系推广到u和v的根节点的关系之上 代码: 1 #include <iostream> 2 #include <cstdio> 3 #incl

POJ1182 食物链 (并查集)*新方法

本文出自:http://blog.csdn.net/svitter 题意: 动物王国中有三类动物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句话,这

POJ1182 食物链 [并查集]

很好的题,分析与题解转自: http://blog.csdn.net/tiantangrenjian/article/details/7085575 http://blog.csdn.net/c0de4fun/article/details/7318642/ 这题不知道为啥写成多组用例不能过,,,oj的一个bug吧~ 食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 26553   Accepted: 7718 De

poj1182食物链-并查集

食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 83337   Accepted: 24925 Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食物链关系进行描述: 第一种说法是"1 X Y",表示X和Y是同

POJ1182 食物链 并查集 好题

食物链 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句话有的是真的,有的是假的.当一句话满足下

# [acwing 240] 食物链 [并查集]

[acwing 240] 食物链 [并查集] 传送门 题意 ABC三种动物,食物链构成一个环形,,给出M个关于彼此关系的描述,判断有多少个假话. 1 X Y表示同类 2 X Y表示X吃Y 思路 本题是并查集的一种比较新颖的用法,并查集一般用来维护集合,但是在这里主要是使用路径压缩来维护点和根之间的距离. 动物之间有三种关系(同类,捕食,被捕食),并且食物链构成环,那么可以使用和根之间的距离模3来区分三种关系,这里并不严格划分集合,主要是借助了并查集中的路径压缩. 红色的线是不存在的,只是为了方便

编程算法 - 食物链 并查集 代码(C)

食物链 并查集 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 有N仅仅动物, 分别编号为1,2,...,N. 全部动物都属于A,B,C中的一种. 已知A吃B, B吃C, C吃A. 按顺序给出两种信息K条. 第一种: x和y属于同一类. 另外一种: x吃y.  信息之间可能会出错和矛盾, 求不对的信息数. 比如: 有N=10仅仅动物, 给定K=7条信息. (1) 1: x=101, y=1; 出错:没有101的动物. (2) 2: x=1,

POJ 1182 (经典食物链 /并查集扩展)

(參考他人资料) 向量偏移--由"食物链"引发的总结 http://poj.org/problem?id=1182这道食物链题目是并查集的变型.非常久曾经做的一次是水过的,这次细致地研究了这"食物链",无非就是运用向量偏移.从曾经节点与节点转化成向量与向量的关系.我们能够把矛盾的产生得益于向量偏移时的结果. 直接引出向量偏移的运用. 以下是POJ一位大牛这样理解的,本人稍有改动. 对于集合里的随意两个元素a,b而言,它们之间必然存在着某种联系,由于并查集中的元素

HDU2473 - Junk-Mail Filter 利用虚拟数组实现删除并查集的节点

HDU2473 - Junk-Mail Filter: http://acm.hdu.edu.cn/showproblem.php?pid=2473 题目大意: M a b,代表a和b是同一类的,S a,代表原先给出的a的信息是错的,现在将其单独分成一类. 求最后一共有多少类邮件. 若只是分类,很直接就会想到并查集.但这里若直接用并查集是会出错的,因为删除的那个节点后面还可能会有其他的子节点,若直接把其删除,结果会出错. 这里就需要用到一个虚拟数组Trick,和Father数组合作,实现"删除&