zoukankan      html  css  js  c++  java
  • 食物链(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 }
  • 相关阅读:
    上传base64编码图片
    mysql
    当程序员老去 揭秘不为人知背后的辛酸故事
    Java中break的作用
    Random类
    使用dsoframer控件出现"Unable to display the inactive document. Click here to reactivate the document."的问题
    给IT新人的15个建议:苦逼程序员的辛酸反省与总结
    XML开发总结
    解决Office软件冲突问题
    PopupMenu控件的使用
  • 原文地址:https://www.cnblogs.com/Ymir-TaoMee/p/9448148.html
Copyright © 2011-2022 走看看