zoukankan      html  css  js  c++  java
  • AC日记——食物链 codevs 1047

    1074 食物链

     

    2001年NOI全国竞赛

     时间限制: 3 s
     空间限制: 64000 KB
     题目等级 : 钻石 Diamond
     
     
     
    题目描述 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)

    思路:

      并查集;

      怎么做呢?

      有人说要用带权并查集

      然而我是蒟蒻我不会

      我们要开三倍的n的father数组

      i表示与i同类的集合

      i+n表示i可以吃的集合

      i+n+n表示i+n可以吃且可以吃i的集合

      然后每次判断是否是符合已有的真话

      不符合ans++

      符合就作为一条新的真话

    来,上代码:

    #include <cstdio>
    
    #define maxn 50001
    #define maxm 100001
    
    using namespace std;
    
    class Finding {
        private:
            int n,m,f[maxn*3],if_z,ans;
            
            char Cget;
            
            inline void read_int(int &now_)
            {
                now_=0,if_z=1,Cget=getchar();
                while(Cget>'9'||Cget<'0')
                {
                    if(Cget=='-') if_z=-1;
                    Cget=getchar();
                }
                while(Cget>='0'&&Cget<='9')
                {
                    now_=now_*10+Cget-'0';
                    Cget=getchar();
                }
                now_*=if_z;
            }
            
        public:
            Finding()
            {
                read_int(n),read_int(m);
                for(int i=1;i<=n*3;i++) f[i]=i;
                int type,x,y;
                for(int i=1;i<=m;i++)
                {
                    read_int(type),read_int(x),read_int(y);
                    if(x>n||y>n)
                    {
                        ans++;
                        continue;
                    }
                    if(type==1)
                    {
                        if(If_same(x,y+n)||If_same(x,y+n+n))
                        {
                            ans++;
                            continue;
                        }
                        else
                        {
                            Merge(x,y);
                            Merge(x+n,y+n);
                            Merge(x+n+n,y+n+n);
                        }
                    }
                    else
                    {
                        if(If_same(x,y)||If_same(x+n+n,y))
                        {
                            ans++;
                            continue;
                        }
                        else
                        {
                            Merge(x+n,y);
                            Merge(x+n+n,y+n);
                            Merge(x,y+n+n);
                        }
                    }
                }
                printf("%d
    ",ans);
            }
            
            int Find(int x)
            {
                if(x==f[x]) return x;
                f[x]=Find(f[x]);
                return f[x];
            }
            
            bool If_same(int x,int y)
            {
                if(Find(x)==Find(y)) return true;
                else return false;
            }
            
            void Merge(int x,int y)
            {
                x=Find(x),y=Find(y);
                if(x!=y) f[x]=y;
            }
    };
    class Finding do_;
    
    int main()
    {
        return 0;
    }
  • 相关阅读:
    贝尔级数
    NOIP2018 退役记
    Codeforces1106F 【BSGS】【矩阵快速幂】【exgcd】
    codeforces1111 简单题【DE】简要题解
    BZOJ4836: [Lydsy1704月赛]二元运算【分治FFT】【卡常(没卡过)】
    BZOJ3771: Triple【生成函数】
    Codeforces 1096G. Lucky Tickets【生成函数】
    Codeforces1099F. Cookies【DP】【线段树】【贪心】【博弈】【沙比提(这是啥算法)】
    Codeforces gym101955 A【树形dp】
    BZOJ3551: [ONTAK2010]Peaks加强版【Kruskal重构树】【主席树】
  • 原文地址:https://www.cnblogs.com/IUUUUUUUskyyy/p/6296597.html
Copyright © 2011-2022 走看看