食物链(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\n",ans);
    73 }

猜你喜欢

转载自www.cnblogs.com/Ymir-TaoMee/p/9448148.html