POJ 1182 食物链 (带权并查集)

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

题解:首先我们要明确并查集的作用:快速判断两个数是否同一集合与快速合并两个集合成一个集合并求出一些节点之间的关系,根据的就是树的特点:每个孩子节点有且仅有一个父节点。这样就用数组记录父节点就还(根就记录自己),合并操作就是合并两个根节点,这儿有个优化就是启发式合并:根记录孩子个数,并把个数少的并到个数大的上面。 不过我们有其他大招:路径压缩,即我们每次查询的时候都把一条线上的所有节点连接到祖先节点,这样每次查找都很快(并查集在路径压缩之后的时间复杂度是阿克曼函数)。依据就是我们只需要知道多个孩子节点的祖先是否一致就能判断是否一个集合,不需要知道树上的结构。我们的权值则是一般记录此节点与父节点的关系,只要满足这个关系可以传递我们就可以模仿矢量计算来处理权值。   这儿我们要明确是有三种关系的:两者同类,吃父节点,被父节点吃,所以权值可以用0,1,2表示   注意有个关键就是当我们知道x与祖先x1的关系,y与祖先y1的关系,x与y的关系时,求x1与y1的关系时,使用矢量 计算: x1->x ->y ->y1 计算
 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <vector>
 6 #include <cstdlib>
 7 #include <iomanip>
 8 #include <cmath>
 9 #include <ctime>
10 #include <map>
11 #include <set>
12 #include <queue>
13 using namespace std;
14 #define lowbit(x) (x&(-x))
15 #define max(x,y) (x>y?x:y)
16 #define min(x,y) (x<y?x:y)
17 #define MAX 100000000000000000
18 #define MOD 1000000007
19 #define pi acos(-1.0)
20 #define ei exp(1)
21 #define PI 3.141592653589793238462
22 #define INF 0x3f3f3f3f3f
23 #define mem(a) (memset(a,0,sizeof(a)))
24 typedef long long ll;
25 ll gcd(ll a,ll b){
26     return b?gcd(b,a%b):a;
27 }
28 bool cmp(int x,int y)
29 {
30     return x>y;
31 }
32 /*n个动物 k句话 有一种循环a吃b 吃c c吃a 开始不知道n种动物关系是什么
33 两种询问:d=1 x y为同类  d=2 x吃y 判断假话条数(关键之违背之前的关系)
34 并查集可以很好解决的满足区间传递关系的区间合并问题,注意一般是多棵树*/
35 const int N=50005;
36 const int mod=1e9+7;
37 int fat[N],ran[N];
38 void Init(int n)//初始化重要
39 {
40     for(int i=0; i<=n; i++){
41         fat[i]=i;//初始化都是指向(看做)自己
42         ran[i]=0;//0同类 1吃父节点 2被父节点吃
43     }
44     return;
45 }
46 int Find(int x)//找寻父节点+路径压缩
47 {
48     if(x==fat[x])
49         return fat[x];
50     int y=Find(fat[x]);
51         ran[x]=(ran[x]+ran[fat[x]])%3;//递归后从祖先节点向后到每个孩子来计算
52     return fat[x]=y;//路径压缩
53 }
54 int Union(int typ,int x,int y)//区间并与查询
55 {
56     int x1=Find(x);
57     int y1=Find(y);
58     if(x1==y1){//共父节点才能判断出关系
59         if((ran[x]-ran[y]+3)%3==typ-1)
60             return 0;
61         return 1;
62     }
63     fat[x1]=y1;//连接两父节点
64     ran[x1]=(-ran[x]+typ-1+ran[y]+3)%3;//使用类似向量方法来计算权值,虽然题目只有两个,但是会出现被吃这种情况,所以要变成3种情况,注意一定要处理负数的情况
65     return 0;
66 }
67 int main()
68 {
69     int n,k,ans;
70     int typ,smt1,smt2;
71     scanf("%d %d",&n,&k);
72         Init(n);
73         ans=0;
74         for(int i=0;i<k; i++){
75             scanf("%d %d %d",&typ,&smt1,&smt2);
76             if(smt1==smt2&&typ==2)
77                 ans++;
78             else if(smt1>n||smt2>n)
79                 ans++;
80             else
81                 ans+=Union(typ,smt1,smt2);
82         }
83         printf("%d\n",ans);
84     return 0;
85 }
时间: 2024-10-13 03:04:48

POJ 1182 食物链 (带权并查集)的相关文章

POJ 1182 食物链 带权并查集

动物王国中有三类动物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句话有的是真的,有的是假的.当一句话满足下列三条之一时,这句话就是假话,否

POJ 1182 食物链 (带权并查集 &amp;&amp; 向量偏移)

题意 : 中文题, 直接去POJ  1182看即可 分析 : 通过普通并查集的整理归类, 能够单纯地知道某些元素是否在同一个集合内.但是题目不仅只有种类之分, 还有种类之间的关系, 即同类以及吃与被吃, 而且重点是题目问的并不是种类是否在一个集合内, 而是考察给出的关系是否矛盾.在解释之前, 先明白一个问题, 对于给出的关系, 如果我不能通过前面的信息来推断出来, 是不是不能够判断现在给出关系的对错?那就将这个信息作为真命题并存储起来, 方便后面判断.有了刚刚前面的陈述, 可以知道两个东西=>

A Bug&#39;s Life POJ - 2492 (带权并查集)

A Bug's Life POJ - 2492 Background Professor Hopper is researching the sexual behavior of a rare species of bugs. He assumes that they feature two different genders and that they only interact with bugs of the opposite gender. In his experiment, indi

poj 1182食物链【种类并查集】

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

poj 1182 食物链(种类并查集 ‘初心者’)

题目链接:http://poj.org/problem?id=1182 借着这题可以好好理解一下种类并查集,这题比较简单但挺经典的. 题意就不解释了,中问题. 关于种类并查集结局方法也是挺多的 1扩增倍数. 就是有几种关系就建立几倍数组,具体方法在这里不详细说了,这种方法有弊端 比较复杂而且内存消耗比较大如果关系比较多就容易爆掉. 2向量的方法. 这种方法要详细解说一下.这个方法好处都有啥.......(自行脑补后面的话) 这个方法的优点占用内存比较小而且比较简洁.只要找到关系就行. 下面就用方

POJ 1182 食物链 (种类并查集)

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

POJ 1182——食物链——————【种类并查集】

食物链 Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 1182 Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食物链关系进行描述: 第一

poj 1703(带权并查集)

Find them, Catch them Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 31840   Accepted: 9807 Description The police office in Tadu City decides to say ends to the chaos, as launch actions to root up the TWO gangs in the city, Gang Dragon

ACWing 240. 食物链 带权并查集

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

POJ - 1182 食物链(种类并查集)

题目链接:http://poj.org/problem?id=1182 题意:三种关系,A吃B, B吃C,C吃A.给出k个句话,如果那句话和前面冲突即为假话 求假话出现的总数. 以前周赛考过一次,感觉好难,就溜了.(逃... 今天看<挑战...>看到有这道题目,感觉是时候来一发了... 因为有三种关系,扩增数组为3*N,每N个分别代表A 种类,B种类,C种类. 题目要求当D=1时,x和y为同类:D=2时,x吃y //默认x为A物种,然后当D=1时,说明y不可能是B和C物种,也就是说他们的爸爸不