食物链(POJ 1182)

Posted ymir-taomee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了食物链(POJ 1182)相关的知识,希望对你有一定的参考价值。

  • 原题如下:
    食物链
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 90935   Accepted: 27329

    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
  • 分析:
    本题中,并不只有属于同一类的信息,还有捕食关系的存在,因此要想办法维护这些关系。
    对于每只动物i,创建3个元素i-A,i-B,i-C,并用这3*N个元素建立并查集,用来维护这些信息:①i-x表示i属于种类x,②并查集里的每一个组表示组内所有元素代表的情况都同时发生或不发生
    对于每一条信息,按照要求进行合并即可,但是要在合并前判断一下是否会产生矛盾。
  • 代码:
     1 #include <cstdio>
     2 
     3 using namespace std;
     4 
     5 int n,k;
     6 int *T,*X,*Y,*par,*r;
     7 
     8 void init(int n)
     9 {
    10     for (int i=0; i<n; i++)
    11     {
    12         par[i]=i;
    13         r[i]=0;
    14     }
    15 }
    16 
    17 int find(int x)
    18 {
    19     if (par[x]==x) return x;
    20     return par[x]=find(par[x]);
    21 }
    22 
    23 void unite(int x, int y)
    24 {
    25     x=find(x);
    26     y=find(y);
    27     if (x==y) return;
    28     if (r[x]<r[y]) par[x]=y;
    29     else 
    30     {
    31         par[y]=x;
    32         if(r[x]==r[y]) ++r[x];
    33     }
    34 }
    35 
    36 bool same(int x, int y)
    37 {
    38     return find(x)==find(y);
    39 }
    40 
    41 int main()
    42 {
    43     scanf("%d %d",&n,&k);
    44     T=new int[k];
    45     X=new int[k];
    46     Y=new int[k];
    47     par=new int[n*3];
    48     r=new int[n*3];
    49     for (int i=0; i<k; i++) scanf("%d %d %d",&T[i],&X[i],&Y[i]);
    50     //元素x,x+n,x+n*2分别表示x-A,X-B,x-C 
    51     init(n*3);
    52     int ans=0;
    53     for (int i=0; i<k; i++)
    54     {
    55         int t=T[i],x=X[i]-1,y=Y[i]-1;
    56         if (x<0 || x>=n || y<0 || y>=n)
    57         {
    58             ++ans;
    59             continue;
    60         }
    61         if (t==1)
    62         {
    63             if (same(x,y+n) || same(x,y+n*2)) ans++;
    64             else for (int j=0; j<3; j++) unite(x+n*j,y+n*j);
    65         }
    66         else 
    67         {
    68             if (same(x,y) || same(x,y+n*2)) ans++;
    69             else for (int j=0; j<3; j++) unite(x+n*j,y+n*((j+1)%3));
    70         }
    71     }
    72     printf("%d
    ",ans);
    73 }

     
















以上是关于食物链(POJ 1182)的主要内容,如果未能解决你的问题,请参考以下文章

食物链 poj 1182

POJ 1182 食物链

食物链(poj1182)

POJ1182 食物链 —— 带权并查集

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

POJ1182 食物链---(经典种类并查集)