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

    背景

    安徽省芜湖市第二十七中学测试题

    NOI 2001 食物链(eat)

    Description:Official
    Data:Official
    Program:JackDavid127

    描述

    动物王国中有三类动物 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 真话

    分析与解:最近刚刚做过一道叫“关押罪犯”的联赛题,偶然间又发现了这道题,仔细一想,发现这根本就是那道题做了一点点小变化而已,所以,没用多久很快就做出来了。看这道题,题目要求我们判假,如果我们用并查集来做这道题,应该何从下手呢?首先,很显然的是,我们必须维护一个点与点关系的集合,通过这个关系集合来判假。原始的并查集只能用于维护“属于同一类“的这种关系,但是这道题却还要求我们维护吃的关系,这样才能针对每一个给出的论断进行判断。维护属于同一组的这种信息很容易实现,但是又如何体现捕食的关系呢?稍加思考,可以这样来转化。针对每只动物,为他们分别创建三个元素,每个元素表示不同的种类信息(具体实现为i表示这只动物是A,i+N就表示是B,i+2*N就表示这只动物是C了),这样,就用N*3个元素来建立并查集,这样,种类信息便成功加进来了。再来,就是维护了。其实很简单,虽然不知道给出的每一个论断(这里指第二种)中,两只动物分别是什么种类的,但事实上无需知道,因为食物链是一个环,随便哪一点选作A都行,只要每种动物的相对关系不变就行。所以,我们把同一个集合中的所有元素都看做符合事实,由于加上了类型信息,所以吃的关系也能判断出来。如此一来,针对每一个论断直接判断是否矛盾,不矛盾,就更新集合,否则是假话,把计数变量加一就可以了。

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn = 200500;
    int n,k;
    int d,a,b;
    int ans;
    int fa[maxn];
    inline int read(){
        char ch=getchar();
        int f=1,x=0;
        while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();};
        while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getchar();};
        return x*f;
    }
    int findf(int x){
        return x == fa[x] ? x : fa[x] = findf(fa[x]);
    }
    int un(int x,int y){
        x = findf(x);
        y = findf(y);
        if(x != y) fa[x] = y;
    }
    bool same(int x,int y){
        x = findf(x);
        y = findf(y);
        return x == y;
    }
    int main(){
        n = read();
        k = read();
        int m = n*3;
        for(int i = 1;i <= m;i++) fa[i] = i;
        for(int i = 1;i <= k;i++){
            d = read();
            a = read();
            b = read();
            if(a > n || b > n){
                ans++;
                continue;
            }
            if(a == b && d != 1){
                ans++;
                continue;
            }
            if(d == 1){
                if(same(a,b+n) || same(a,b+2*n)){
                    ans++;
                    continue;
                }
                un(a,b);
                un(a+n,b+n);
                un(a+n*2,b+n*2);
            }
            if(d == 2){
                if(same(a,b) || same(a,b+n*2)){
                    ans++;
                    continue;
                }
                un(a,b+n);
                un(a+n,b+n*2);
                un(a+n*2,b);
            }
        }
        cout<<ans;
        return 0;
    }

    特别注意补集思想的运用,注意吃与被吃构成环,不需要像关押罪犯一样相互放置!

    还有一篇博客写的比较麻烦,他把所有的点都并到一个集合里去,再用节点与代表元素的关系推出相互关系,比较麻烦

    http://blog.csdn.net/c0de4fun/article/details/7318642/

  • 相关阅读:
    Oracle 按一行里某个字段里的值分割成多行进行展示
    Property or method "openPageOffice" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by
    SpringBoot 项目启动 Failed to convert value of type 'java.lang.String' to required type 'cn.com.goldenwater.dcproj.dao.TacPageOfficePblmListDao';
    Maven 设置阿里镜像
    JS 日期格式化,留作参考
    JS 过滤数组里对象的某个属性
    原生JS实现简单富文本编辑器2
    Chrome控制台使用详解
    android权限(permission)大全
    不借助第三方网站四步实现手机网站转安卓APP
  • 原文地址:https://www.cnblogs.com/hyfer/p/5879465.html
Copyright © 2011-2022 走看看