POJ1182——食物链

作者: 周九九丶 | 来源:发表于2018-06-01 23:40 被阅读3次

问题描述

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


解决思路

  • 并查集是维护“属于同一组”的数据结构,通过并查集可以将两个组合并,以及判断两个元素是否属于同一组。
  • 在本题中,并不只有属于同一类的信息,还有捕食关系的存在。
  • 对于每只动物创建三个元素,i-A、i-B、i-C,并用这3×N个元素建立并查集:
    1)i-X表示“i属于种类X”
    2)并查集内的每一个元素表示组内所有元素代表的情况同时发生或不发生。例如,如果i-A、j-B属于同一个组,则说明i属于种类A那么j一定属于种类B,反之亦然。
  • 对于第一种说法,合并i-A和j-A、i-B和j-B、i-C和j-C
    对于第二种说法,合并i-A和j-B、i-B和j-C、i-C和j-A
  • 在合并之前要判断合并是否会产生矛盾:
    对于第一种说法,要判断i-A和j-B、j-C是否已经在同一组
    对于第二种说法,要判断i-A和j-A、j-C是否已经在同一组

AC代码

#include "stdio.h"
#include "stdlib.h"

int N;
int K;
int p[150010];
int r[150010];
int res;

//initial the sets
void init(){
    for(int i = 0; i < 3 * N; i++){
        p[i] = i;
    }
}
//Find(x) return the root of x
int Find(int x){
    if(x == p[x]) return x;
    else return p[x] = Find(p[x]);
}

//Union(x, y) union the sets of x and y
void Union(int x, int y){
    int xRoot = Find(x);
    int yRoot = Find(y);

    if(xRoot == yRoot) return;
    if(r[xRoot] < r[yRoot]) p[xRoot] = yRoot;
    else if(r[xRoot] > r[yRoot]) p[yRoot] = xRoot;
    else{
        p[yRoot] = xRoot;
        r[xRoot]++;
    }
}

bool sameRoot(int x, int y){
    //printf("root of %d: %d\n", x, Find(x));
    //printf("root of %d: %d\n", y, Find(y));
    return Find(x) == Find(y);
}

int main(){
    scanf("%d %d", &N, &K);
    init();
    int D, X, Y;
    for(int i = 0; i < K; i++){
        scanf("%d %d %d", &D, &X, &Y);
        //printf("%d %d %d\n", D, X, Y);
        if(X > N || Y > N || (D == 2 && X == Y)) {
            //printf("Input illegal\n");
            res++;
            continue;
        }
        int xA = 3 * X - 3;//x is A
        int xB = 3 * X - 2;//x is B
        int xC = 3 * X - 1;//x is C 
        int yA = 3 * Y - 3;//y is A
        int yB = 3 * Y - 2;//y is B
        int yC = 3 * Y - 1;//y is C
        if(D == 1){
            if(sameRoot(xA, yB) || sameRoot(xA, yC)){
                //printf("conflict:%d and %d are the same\n", X, Y);
                res++;
                continue;
            }
            if(sameRoot(xA, yA)) continue;
            //printf("Union:%d and %d are the same\n", X, Y);
            Union(xA, yA);
            Union(xB, yB);
            Union(xC, yC);
        }   
        if(D == 2){
            if(sameRoot(xA, yA) || sameRoot(xA, yC)){
                //printf("conflict:%d eat %d\n", X, Y);
                res++;
                continue;
            }
            if(sameRoot(xA, yB)) continue;
            //printf("Union:%d eat %d\n", X, Y);
            Union(xA, yB);
            Union(xB, yC);
            Union(xC, yA);
        }
    }
    printf("%d\n", res);
}

相关文章

  • POJ1182——食物链

    问题描述 有三类动物A,B,C,这三类动物的食物链构成了有趣的环形:A吃B, B吃C,C吃A。 现有N个动物,以1...

  • POJ1182(食物链)

    链接:https://vjudge.net/problem/POJ-1182思路:由于已经确定了只有三种关系并且为...

  • 食物链POJ1182总结

    这道题是用并查集来解。并查集可以高效的查找某个元素是否属于一个集合。敲代码过程中一次遇到了如下问题: new 的使...

  • 商业位势决定收益极限

    自然界中有“食物链”,“食物链”中不同的生物处于不同的位置,我们将食物链中的位置称之为营养级。比如青草——昆虫——...

  • 生物大量灭绝的原因及航天研究的意义

    在一条食物链中,能量流动的特点是逐级减少的,因此,食物链中生物越靠进食物链的后方,数量就会越少。 例如,一条简单的...

  • 食物链

    又在出差,简短。最近去一个项目,做一个变更~非常不合理的变更。然后,看到了工地上一群人在施工~三伏天,大汗淋漓。突...

  • 食物链

    嗜杀者,都是活在食物链末端。当自食其力都非常艰难时,选择了破坏整个食物链来葬送自己。 今天,公元2...

  • 食物链

    生产者。阳光、空气、水无生命痕迹的物质中自我满足轻吐出颜色、芬芳和氧气它是能量转化的原点不存在消化器官终将被咀嚼默...

  • 食物链

    傍晚的时候,六奶奶送来一罐辣酱。 花生碎和萝卜块做底,腌出酸味的山野菜里浸着细细密密的青椒末。甜辣口儿,一口下去,...

  • 食物链

    八甲镇上新开了间饭店,叫上下。 据说店内只设有两道菜,一道名为上,另一道则叫下。 世上入我店内者分上下两等人,上这...

网友评论

    本文标题:POJ1182——食物链

    本文链接:https://www.haomeiwen.com/subject/lujlsftx.html