papamelon 241. 食物链(挑战程序设计竞赛)

地址 https://www.papamelon.com/problem/241

有 N 只动物, 分别编号为 1,2,3...,N。

所有动物都属于 A,B,C 中的一种。已知 
A 吃 B、
B 吃 C、
C 吃 A。
按顺序给出下面的两种信息共 
K 条:
第一种: 
1 x y 表示 ,x,y 属于同一种类
第二种: 
2 x y 表示 x 吃 y
这些信息有可能会出错。和之前已给出的信息矛盾, 也有的信息可能给出的 x 和 y 不在1,2,3...,N 的范围内。

求在 K 条信息中有多少条是不正确的。
先出现的信息被认为是正确的。后出现的信息如果和前面的矛盾,则被认为是错误的。

输入
第一行包含两个整数 N 和 K
接下来的 
K 行,每行有三个整数 
t x y,分别表示信息的类型(1≤t≤2)以及 x 和 y
1≤N≤50000,0≤K≤100000
输出
一个整数,表示有多少条不正确的信息
样例 1
输入
100 7
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5
输出
3

解答
并查集扩展域的好题
给出的动物 xy一定在ABC之中,等价于动物关系要么是同类要么是天敌(A吃B 或者B吃A)

那么判断 ab a+N b+N a+2N b+2N是否在同一个并查集里 就能判断话的真伪了。

#include <iostream>

using namespace std;
const int N = 50010;
int f[N * 3];   // n~a 2n~a的食物 3n~a的天敌

//并查集 初始化
void init() {
    for (int i = 0; i < N * 3; i++) {
        f[i] = i;
    }
}

//并查集查找
int find(int x) {
    if (f[x] != x) {
        f[x] = find(f[x]);
    }
    
    return f[x];
}


//并查集合并
void merge(int a, int b) {
    a = find(a); b = find(b);
    if (a < b) {
        f[b] = a;
    }
    else {
        f[a] = b;
    }
}

int n, k;

int main()
{
    cin >> n >> k;
    int ans = 0;
    init();
    for (int i = 0; i < k; i++) {
        int d, a, b;
        cin >> d >> a >> b;
        //如果动物编号超过限制 假话
        if (a > n || b > n  ) { 
            ans++; continue; 
        }
        else if(d == 1) {
            //ab同类的语句
            a = find(a); b = find(b);
            //判断a和b是同类的情况下  a能和b的食物天敌在同一个集合中  有冲突  假话
            if (a == find(b + n) || a == find(b + 2 * n) ) {
                ans++; 
            }
            else {
                //真话 合并它们的关系 还要合并他们的天敌和食物的关系
                merge(a, b); merge(a+n, b+n); merge(a+2*n, b+2*n);
            }
        }
        else if (d == 2) {
            //a吃b 也就是 b是a的食物 的语句
            a = find(a); b = find(b);
            //a吃b  如果还有a和b同类或者 a是b的食物 ,冲突判断为假话
            if (a == b || a == find(b + n)) {
                ans++;
            }
            else {
                //不冲突 合并它们的关系  a是b的天敌  a的食物是b的同类 a的天敌是b的食物
                merge(a + n, b); merge(a + 2 * n, b + n); merge(a,b+2*n);
            }
        }
    }

    cout << ans << endl;

    return 0;
}

我的视频题解空间

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章