AcWing:240. 食物链(扩展域并查集)

Posted buhuiflydepig

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AcWing:240. 食物链(扩展域并查集)相关的知识,希望对你有一定的参考价值。

动物王国中有三类动物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和K句话,输出假话的总数。

输入格式

第一行是两个整数N和K,以一个空格分隔。

以下K行每行是三个正整数 D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。

若D=1,则表示X和Y是同类。

若D=2,则表示X吃Y。

输出格式

只有一个整数,表示假话的数目。

数据范围

1N500001≤N≤50000,
0K1000000≤K≤100000

输入样例:

100 7
1 101 1 
2 1 2
2 2 3 
2 3 3 
1 1 3 
2 3 1 
1 5 5

输出样例:

3

 

题解:

扩展域并查集:我们把每个动物拆成3个节点,分别是同类域xself,捕食域xeat,天敌域xenemy。

#include <iostream>
#include <cstdio>

using namespace std;

const int maxn = 3e5+7;

int f[maxn];

int get(int x) 
    if(x == f[x]) 
        return f[x];
    
    int root = get(f[x]);
    return f[x] = root;


int main() 
    int n, m;
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= 3 * n; i++) 
        f[i] = i;
    
    int ans = 0;
    while(m--) 
        int op, x, y;
        scanf("%d %d %d", &op, &x, &y);
        int x_self = x, x_eat = x + n, x_enemy = x + n + n;
        int y_self = y, y_eat = y + n, y_enemy = y + n + n;
        if(x > n || y > n)     //动物编号不存在
            ans++;
         else if(op == 1)     //x和y是同类关系
            if(get(x_eat) == get(y_self) || get(x_self) == get(y_eat))     //如果x捕食的物种和y的同类在同一集合,或者x的同类和y捕食的物种在同一集合,那么不成立,此话是假
                ans++;
             else     //合并同类物种
                f[get(x_self)] = get(y_self);
                f[get(x_eat)] = get(y_eat);
                f[get(x_enemy)] = get(y_enemy);
            
         else     //x和y是捕食关系,x吃y
            if(get(x_self) == get(y_self) || get(x_self) == get(y_eat))     //如果x的同类和y的同类在同一集合,或者x的同类和y捕食的物种在同一集合,那么不成立,此话是假
                ans++;
             else     //合并同类物种
                f[get(x_eat)] = get(y_self);
                f[get(x_self)] = get(y_enemy);
                f[get(x_enemy)] = get(y_eat);
            
        
    
    printf("%d\n", ans);
    return 0;

 

以上是关于AcWing:240. 食物链(扩展域并查集)的主要内容,如果未能解决你的问题,请参考以下文章

ACWing 240. 食物链 带权并查集

Noi2001 食物链(扩展域并查集)

P2024 [NOI2001] 食物链(并查集)

扩展域并查集

[数据结构总结] 扩展域并查集

240. 食物链(并查集+数论)