zoukankan      html  css  js  c++  java
  • POJ 1182 食物链 (关系并查集)

    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),输出假话的总数。

    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


    思路:根据题意想A,B,C构成mod3的关系,如果D=2表示x吃y,这时会出问题:x吃y,y吃z,那么x到z的关系为4%3=1,于是x到z的关系为x与y是同类;
    但是z到x的关系为3-1=2,即z吃x,于是出现矛盾。
    所以我们应该使0表示同类,1,2分别表示吃与被吃的关系。这样才能推通。 如果之前的话中x与y的关
    系还不能被推出,那么合并x与y,并算出x与y的关系;如果之前的话中已知x与y的关系,那么判断当前x
    与y的关系是否与之前说过的话有冲突,如果有,那
    么谎话++,否则不做操作;题目中给的d=2时,x吃x的情况其实可以看做是同一集合当前谎话与之前说过的话的冲突来处理


     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 int const N=50010;
     7 int f[N];
     8 int rela[N];
     9 
    10 int Find(int a)
    11 {
    12     int r=0;
    13     int b=a;
    14     while(b!=f[b])
    15     {
    16         r += rela[b];
    17         b=f[b];
    18     }
    19     while(f[a]!=b)
    20     {
    21         int tmp = f[a];
    22         f[a]=b;
    23         r -= rela[a];
    24         rela[a] += r;
    25         a = tmp;
    26     }
    27     return b;
    28 }
    29 
    30 void Union(int x,int y,int r)
    31 {
    32     int fx=Find(x);
    33     int fy=Find(y);
    34     rela[fx]=rela[y]-rela[x]+r;
    35     f[fx]=fy;
    36 }
    37 
    38 int main()
    39 {
    40     int m,n;
    41     scanf("%d%d",&m,&n);
    42 
    43         for(int i=1;i<=m;i++)
    44         {
    45             f[i]=i;
    46             rela[i]=0;
    47         }
    48         int k=0;
    49         while(n--)
    50         {
    51             int d,x,y;
    52             scanf("%d%d%d",&d,&x,&y);
    53             if(x>m||y>m) k++;
    54             else if(Find(x)==Find(y))
    55             {
    56                 if(((rela[x]-rela[y])%3+3)%3!=d-1) k++;
    57             }
    58             else if(Find(x)!=Find(y))
    59                 Union(x,y,d-1);
    60         }
    61         printf("%d
    ",k);
    62 
    63     return 0;
    64 }
  • 相关阅读:
    【Python】【Nodejs】下载单张图片到本地,Python和Nodejs的比较
    【pyhon】nvshens图片批量下载爬虫1.01
    【pyhon】Python里的字符串查找函数find和java,js里的indexOf相似,找到返回序号,找不到返回-1
    【pyhon】nvshens图片批量下载爬虫
    【python】下载网络文件到本地
    【python】列出http://www.cnblogs.com/xiandedanteng中所有博文的标题
    【python】列出http://www.cnblogs.com/xiandedanteng/p/中的标题
    【python】如何安装requests
    【python】如何安装BeautifulSoup4
    day16_ajax学习笔记
  • 原文地址:https://www.cnblogs.com/Amidgece/p/5742688.html
Copyright © 2011-2022 走看看