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;
}

我的視頻題解空間

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