zoukankan      html  css  js  c++  java
  • poj---1182---食物链

    poj---1182---食物链
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 62711   Accepted: 18404
    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
    第一行是两个整数N和K,以一个空格分隔。 
    以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。 
    若D=1,则表示X和Y是同类。 
    若D=2,则表示X吃Y。
    Output
    只有一个整数,表示假话的数目。
    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
    Source
    比较经典的并查集的题目,主要是要理解路径压缩的过程。
    用0  1   2 分别表示A B C的关系。
    0吃1,1吃2,2吃0.
    注意这个编号都是以根结点为参照的,不是绝对的。
    开一个val数组,一开始这个数组为0,所有的点都是独立的,不是相连的,没有关系。
    慢慢加入点之后,把有关系的合并在一起,并且编号的相对大小确定一个集合中的关系。
    这题比较坑的地方就是,一定要单组输入,否则会WA。
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cmath>
    #include<algorithm>
    using namespace std;
     
    const int maxn=100007;
    const int INF=0x3f3f3f3f;
    int father[maxn];
    int val[maxn];
     
    int Find(int x)
    {
        if(father[x]==-1)return x;
        int tmp=Find(father[x]);
     
        val[x]+=val[father[x]];
        val[x]%=3;
        return father[x]=tmp;
    }
     
    int main()
    {
        int n, m;
        scanf("%d %d", &n, &m);
     
        int ans=0;
        memset(father, -1, sizeof(father));
        memset(val, 0, sizeof(val));
     
        while(m--)
        {
            int D, x, y;
            scanf("%d %d %d", &D, &x, &y);
     
            if(x>n || y>n)
            {
                ans++;
                continue;
            }
     
            int a=Find(x);
            int b=Find(y);
            if(a==b)
            {
                if(D==1&&val[x]!=val[y])ans++;
                if(D==2&&(val[x]+1)%3!=val[y])ans++;
            }
     
            else
            {
                if(D==1)
                {
                    father[b]=a;
                    val[b]=val[x]-val[y];
                    val[b]=(val[b]+3)%3;
                }
                else
                {
                    father[b]=a;
                    val[b]=val[x]-val[y]+1;
                    val[b]=(val[b]+3)%3;
                }
            }
        }
        printf("%d
    ", ans);
     
        return 0;
    }
    View Code
     
  • 相关阅读:
    MySQL 操作命令梳理(1)-- 索引
    Linux下对LVM逻辑卷分区大小调整 [针对xfs和ext4文件系统]
    CentOS6 虚拟机安装后,无Iptables配置文件
    Linux系统权限设置
    完整部署CentOS7.2+OpenStack+kvm 云平台环境(2)--云硬盘等后续配置
    完整部署CentOS7.2+OpenStack+kvm 云平台环境(3)--为虚拟机指定固定ip
    Android消息推送怎么实现?
    Android 下拉刷新
    Windows 10 周年更新正式版下载 + win10 快捷键
    markdown编辑器使用建议
  • 原文地址:https://www.cnblogs.com/w-y-1/p/5720833.html
Copyright © 2011-2022 走看看