zoukankan      html  css  js  c++  java
  • codevs1074: 食物链 2001年NOI全国竞赛

    题目描述 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 Description

    第一行是两个整数N和K,以一个空格分隔。   

    以下K行每行是三个正整数D,X,Y,两数之间用一个空格隔开,其中 D 表示说法的种类。   

    若D=1,则表示X和Y是同类。   

    若D=2,则表示X吃Y。

    输出描述 Output Description

    只有一个整数,表示假话的数目。

    样例输入 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

    数据范围及提示 Data Size & Hint

    输入文件  

     对7句话的分析 100 7

    1 101 1  假话

    2 1 2    真话

    2 2 3    真话

    2 3 3    假话

    1 1 3    假话

    2 3 1    真话

     1 5 5    真话

    NOI 2001 食物链(eat)

    题解

    两种写法:1、建立虚点;2、带权并查集,关于这道题网上题解很详细,不再解释了

    1、虚点写法

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #define maxn 50010
     5 using namespace std;
     6 int fa[maxn*3],n,k,ans;
     7 int find(int x)
     8 {
     9     return x==fa[x]?x:fa[x]=find(fa[x]);
    10 }
    11 bool ok(int x,int y)
    12 {
    13     int fx=find(x);
    14     int fy=find(y);
    15     if(fx==fy)return true;
    16     return false;
    17 }
    18 void unite(int x,int y)
    19 {
    20     int fx=find(x);
    21     int fy=find(y);
    22     if(fx!=fy)fa[fy]=fx;
    23 }
    24 int main()
    25 {
    26     int p,x,y;
    27     scanf("%d%d",&n,&k);
    28     for(int i=1 ; i<3*n ; ++i)fa[i]=i;
    29     for(int i=1 ; i<=k ; ++i)
    30     {
    31         scanf("%d%d%d",&p,&x,&y);
    32         if(x>n||y>n)
    33         {
    34             ++ans;
    35             continue;
    36         }
    37         if(p==1)
    38         {
    39             if(ok(x,y+n)||ok(x,y+2*n))++ans;
    40             else 
    41             {
    42                 unite(x,y);unite(x+n,y+n);unite(x+2*n,y+2*n);
    43             }
    44         }
    45         else 
    46         {
    47             if(ok(x,y)||ok(x,y+2*n))++ans;
    48             else 
    49             {
    50                 unite(x,y+n);unite(x+n,y+2*n);unite(x+2*n,y);
    51             }
    52         }
    53     }
    54     printf("%d",ans);
    55     return 0;
    56 }

    2、带权并查集

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #define maxn 50005
     5 using namespace std;
     6 int n,k,ans,fa[maxn],d[maxn];
     7 int find(int x)
     8 {
     9     if(fa[x]==x)return x;
    10     int t=find(fa[x]);
    11     d[x]=(d[x]+d[fa[x]]+3)%3;
    12     fa[x]=t;
    13     return t;
    14 }
    15 int unite(int tmp,int x,int y)
    16 {
    17     int fx=find(x);
    18     int fy=find(y);
    19     if(fx==fy)
    20     {
    21         if((d[x]-d[y]+3)%3==tmp-1)return 0;
    22         return 1;
    23     }
    24     fa[fx]=fy;
    25     d[fx]=(d[y]+tmp-1-d[x]+3)%3;
    26     return 0;
    27 }
    28 int main()
    29 {
    30     int p,x,y;
    31     scanf("%d%d",&n,&k);
    32     for(int i=1 ; i<=n ; ++i)fa[i]=i;
    33     for(int i=1 ; i<=k ; ++i )
    34     {
    35         scanf("%d%d%d",&p,&x,&y);
    36         if(p==2&&x==y)++ans;
    37         else if(x>n||y>n)++ans;
    38         else ans+=unite(p,x,y);
    39     }
    40     printf("%d",ans);
    41     return 0;
    42 }
  • 相关阅读:
    使用CustomValidate自定义验证控件
    C#中金额的大小写转换
    Andriod出错之Unable to build: the file dx.jar was not loaded from the SDK folder!
    VC 编写的打字练习
    机房工作笔记Ping只有单向通
    web服务协同学习笔记(1)
    Dll 学习3 将MDI子窗口封装在DLL中
    机房工作学习文件共享
    Andriod出错之Failed to find an AVD compatible with target 'Android 2.2'
    Andriod出错之wrapper was not properly loaded first
  • 原文地址:https://www.cnblogs.com/fujudge/p/7577737.html
Copyright © 2011-2022 走看看