zoukankan      html  css  js  c++  java
  • NOI2001食物链

    描述

    动物王国中有三类动物 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),输出假话的总数。

    格式

    输入格式

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

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

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

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

    输出格式

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

    样例1

    样例输入1[复制]

     
    100 7
    1 101 1
    2 1 2
    2 2 3
    2 3 3
    1 1 3
    2 3 1
    1 5 5

    样例输出1[复制]

     
    3

    限制

    1S

    提示

    并查集
    对样例的解释
    输入文件 对7句话的分析
    100 7
    1 101 1 假话
    2 1 2 真话
    2 2 3 真话
    2 3 3 假话
    1 1 3 假话
    2 3 1 真话
    1 5 5 真话 

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<iostream>
     6 #include<vector>
     7 #include<map>
     8 #include<set>
     9 #include<stack>
    10 #include<string>
    11 #include<algorithm>
    12 #define maxn 150000+50
    13 #define inf 0x7fffffff
    14 #define  xiao 1e-9
    15 using namespace std;
    16 int fa[maxn],p[maxn],n,m; 
    17 void prepared()//初始化 
    18 {
    19     for(int i=1;i<=n*3;++i) p[i]=i;
    20     for(int i=1;i<=n;++i)
    21     {
    22         fa[i]=i+n;
    23         fa[i+n]=i+2*n;
    24         fa[i+2*n]=i;
    25     }
    26 }
    27 int find(int x)//每个动物群的代表元素 
    28 {
    29     if(p[x]!=x) p[x]=find(p[x]);
    30     return p[x];
    31 }
    32 void work()
    33 {
    34     int ans=0;
    35     int q,x,y;
    36     scanf("%d",&m);
    37     for(int i=1;i<=m;++i)
    38     {
    39         scanf("%d%d%d",&q,&x,&y);
    40         if(x>n||y>n) {ans++;continue;}
    41         int a[3],b[3];//a,b为两种动物维护的三个域 
    42         a[0]=find(x),b[0]=find(y);//代表元素 
    43         a[1]=fa[a[0]],a[2]=fa[a[1]];//a[1]为这种动物的被吃域,a[2]为吃域 
    44         b[1]=fa[b[0]],b[2]=fa[b[1]];//同上 
    45         bool flag=false;
    46         for(int i=0;i<3;++i)
    47         {
    48             if(a[0]==b[i]) {flag=true;break;}//是否在一个环内 
    49         }
    50         if(q==1)
    51         {
    52             if(flag) 
    53             {
    54                 if(a[0]!=b[0]) ans++;//如果代表元素不同说明不是一类,此话为假 
    55             }
    56             else
    57             {
    58                 for(int i=0;i<3;++i) p[b[i]]=a[i];//合并操作 
    59             }
    60         }
    61         else
    62         {
    63             if(x==y) {ans++;continue;}
    64             if(flag==true) 
    65             {
    66                 if(fa[b[0]]!=a[0])     ans++;//如果b的被吃对象不是 a,此话为假 
    67             }
    68             else 
    69             {for(int i=0;i<3;++i) p[b[i]]=a[(i+2)%3];}//等价于{p[b[0]]=a[2];p[b[1]]=a[0];p[b[2]]=a[1];}
    70         }
    71     }
    72     cout<<ans;
    73 }
    74 int main()
    75 {
    76     scanf("%d",&n);
    77     prepared();
    78     work();
    79     return 0;
    80 }
  • 相关阅读:
    程序员必看书籍(转载)
    JBPM的ORACLE脚本
    XFire构建web service客户端的五种方式
    为什么中国出不了facebook和Twitter?
    用dwr封装表单项提交表单
    Java 程序员容易犯的10个SQL错误
    SQL语句优化方法30例
    sqlserver sql语句查看分区记录数、查看记录所在分区
    SQL Case when 的使用方法
    sqlserver sql语句附加 分离数据库
  • 原文地址:https://www.cnblogs.com/TYH-TYH/p/4940626.html
Copyright © 2011-2022 走看看