1. 程式人生 > >P2024 [NOI2001]食物鏈(並查集)

P2024 [NOI2001]食物鏈(並查集)

題目描述

動物王國中有三類動物 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 句話有的是真

的,有的是假的。當一句話滿足下列三條之一時,這句話就是假話,否則就是真話。

• 當前的話與前面的某些真的話衝突,就是假話

• 當前的話中 X 或 Y 比 N 大,就是假話

• 當前的話表示 X 吃 X,就是假話

你的任務是根據給定的 N 和 K 句話,輸出假話的總數。

輸入輸出格式

輸入格式:

從 eat.in 中輸入資料

第一行兩個整數,N,K,表示有 N 個動物,K 句話。

第二行開始每行一句話(按照題目要求,見樣例)

輸出格式:

輸出到 eat.out 中

一行,一個整數,表示假話的總數。

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
int n,k,d[100010*3],g,a,b,ans;//分為3類,1吃2,2吃3,3吃1
int f(int x){return d[x]==x?x:d[x]=f(d[x]);}
int main(){
    cin>>n>>k;//N 個動物,K 句話。
    //第一種說法是“1 X Y”,表示 X 和 Y 是同類。       第二種說法是“2 X Y”,表示 X 吃 Y 。
    for(int i=1;i<=n*3;i++)d[i]=i;
    for(int i=0;i<k;i++){
        cin>>g>>a>>b;
        if(a>n||b>n){
            ans++;//cout<<"月結"<<endl;
            continue;
        }
        if(g==1){
            if(f(a+n)==f(b)||f(a)==f(b+n))ans++;//2和1在一類
            else{//a和b在一類
                int x=f(a),y=f(b);
                d[x]=y;
                x=f(a+n),y=f(b+n);
                d[x]=y;
                x=f(a+n+n),y=f(b+n+n);
                d[x]=y;
            }
        }else {
            if(f(a)==f(b)||f(a)==f(b+n))ans++;//a和b是一類
            else{
                int x=f(a+n),y=f(b);//1和2
                d[x]=y;
                x=f(a+n+n),y=f(b+n);//3和2
                d[x]=y;
                x=f(a),y=f(b+n+n);//1和3
                d[x]=y;
            }
        }
    }
    cout<<ans;
    return 0;
}