zoukankan      html  css  js  c++  java
  • luogu2024 食物链(eat)

    1074 食物链

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

    题目分析:

    这道题的思路与关押罪犯类似,使用的方法为带权并查集。

    而对于输入的关系:

    1.如果x或y>n,或x==y,pd=2【实际操作时我将pd-1了所以会有些不一样】(即同种动物自己吃自己,这些均为错误的)。

    2.如果x和y之并没有直接或间接的关系,那么必然不会错误,

    (fx表示x的祖先,fy表示y的祖先)

    (1)pd=1 将fx的祖先与fy的祖先并在一起,并记录fy到fx的距离(对于距离应该进行mod3,因为在食物链中动物只有三种状态0,1,2且处理使1吃0,0吃2,2吃1)为y到fy距离减去x到fx的距离。

    (2)pd=2 基本同上,不过由于是天敌,距离要加1。

    3.如果x和y已经有关系。

    (1) 若输入满足原有关系,则不做处理;

    (2)若不满足,则该句为假。

    #include<cstdio>
    #define N 50005
    int f[N],d[N];//f[i]表示i的父亲,d[i]表示i到f[i]的距离。
    int read()
    {
        char c;
        while((c=getchar())<'0'||c>'9');
        int re=c-'0';
        while((c=getchar())>='0'&&c<='9') re=(re<<1)+(re<<3)+c-'0';
        return re;
    }//读入优化
    int find(int a)
    {
        if(!f[a]) return a;
        int t=find(f[a]);
        d[a]+=d[f[a]];
        d[a]%=3;
        return f[a]=t;//路径压缩是应该顺便将权也加上根节点
    }
    int main()
    {
        int n=read(),k=read(),ans=0;
        while(k--)
        {
            int pd=read()-1,x=read(),y=read();
            if(x>n||y>n||(pd==1&&x==y)) ans++;//讲解1
            else
            {
                int fx=find(x),fy=find(y);
                if(fx==fy)
                {
                    if((d[x]-d[y]+3)%3!=pd) ans++;//讲解3
                }
                else f[fx]=fy,d[fx]=(d[y]-d[x]+pd+3)%3;//讲解2
            }
        }
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    强连通分量 Tarjan
    【二叉搜索树】hdu 3791
    【二叉树】hdu 1622 Trees on the level
    【二叉树】hdu 1710 Binary Tree Traversals
    【leetcode】lower_bound
    【leetcode dp】629. K Inverse Pairs Array
    【leetcode最短路】818. Race Car
    【leetcode 字符串】466. Count The Repetitions
    【leetcode dp】132. Palindrome Partitioning II
    【leetcode dp】Dungeon Game
  • 原文地址:https://www.cnblogs.com/bzmd/p/6017695.html
Copyright © 2011-2022 走看看