• 【NOI2001】【洛谷P2024】食物链


    问题描述

    输入格式

    输出格式

    样例输入

    100 7

    1 101 1

    2 1 2

    2 2 3

    2 3 3

    1 1 3

    2 3 1

    1 5 5

    样例输出

    3

    数据范围

    题解

    动物王国的动物分为三个集合A,B,C,其中A吃B,B吃C,C吃A。我们用并查集表示这些集合间的关系

    对于两个动物x,y,它们之间存在3种关系,即x,y是同类,x吃y,或y吃x

    我们不知道两个动物是A,B,C中的哪两种,但是我们知道它们之间的关系一定在以上3种关系之间

    对于一个动物x,不妨设x+n表示吃x的动物所在的集合,x+n*2表示被x吃的动物所在的集合

    对于每一句话,若存在动物的编号大于n,显然这句话是假的

    我们先讨论集合的合并

    若x和y是同类,那么吃x的动物和吃y的动物在同一个集合,被x吃的动物和被y吃的动物在同一个集合;即将x和y所在集合合并,将x+n和y+n所在集合合并,将x+n*2和y+n*2所在集合合并

    若x吃y,则x和吃y的动物在同一个集合,y和被x吃的动物在同一个集合,即将x和y+n所在集合合并,将y和x+n*2所在集合合并。由题干描述的3种动物的捕食关系可知,还存在一个和x,y都不属于同一个集合的z,满足y吃z且z吃x。那么z所在集合应和y+n*2所在集合合并,且和x+n所在集合合并,我们可以把y+n*2和x+n所在集合合并即表示z所在集合。

    接下来我们讨论判断一句话的真假

    若是第一种说法,若这句话为真,则在已知的关系中必不存在x吃y,或y吃x,或x吃z,z吃y,或y吃z,z吃x,否则这句话为假。

    若是第二种说法,若这句话为真,则已知关系中必不存在x和y属于同一类,并且吃x的动物和吃y的动物不属于同一类,被x吃的动物和被y吃的动物不属于同一类(因为任意两个动物如果不是同类则只存在两种关系,即直接的吃与被吃,所以若吃两个动物的动物属于同一类,则这两个动物必属于同一类,被两个动物吃的动物亦然),否则这句话为假

     1 #include <cstdio>
     2 int n,m,f[150005],ans;
     3 int find(int x)
     4 {
     5     if (f[x]==x) return x;
     6     return f[x]=find(f[x]);
     7 }
     8 int main()
     9 {
    10     int i,j,p,x,y,fx,fy,fx1,fy1,fx2,fy2;
    11     //  x+n    捕食者 
    12     //  x+n*2  被捕食者 
    13     scanf("%d%d",&n,&m);
    14     for (i=1;i<=n*3;i++)
    15       f[i]=i;    
    16     while (m--)
    17     {
    18         scanf("%d%d%d",&p,&x,&y);
    19         if (x>n || y>n)
    20         {
    21             ans++;
    22             continue;
    23         }
    24         fx=find(x);  fy=find(y);
    25         fx1=find(x+n);  fy1=find(y+n);
    26         fx2=find(x+n*2);  fy2=find(y+n*2);
    27         if (p==1)
    28         {
    29             if (fx1==fy || fx2==fy || fx1==fy2 || fx2==fy1)
    30             {
    31                 ans++;
    32                 continue;
    33             }
    34             f[fx]=fy;  f[fx1]=fy1;  f[fx2]=fy2;
    35         }
    36         else
    37         {
    38             if (fx1==fy1 || fx1==fy || fx2==fy1)
    39             {
    40                 ans++;
    41                 continue;
    42             }
    43             f[fx]=fy1;  f[fx1]=fy2;  f[fx2]=fy;
    44         }
    45     }
    46     printf("%d",ans);
    47     return 0;
    48 }
  • 相关阅读:
    祈澈菇凉的高端知识资源分享星球开通
    使用mpvue开发小程序教程(五)
    使用mpvue开发小程序教程(四)
    使用mpvue开发小程序教程(三)
    使用mpvue开发小程序教程(二)
    使用mpvue开发小程序教程(一)
    手把手教你用vue-cli构建一个简单的路由应用
    wangEditor
    从列表中或数组中随机抽取固定数量的元素组成新的数组或列表
    js学习总结----核心解读
  • 原文地址:https://www.cnblogs.com/rabbit1103/p/13888661.html
Copyright © 2020-2023  润新知