[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 句話,輸出假話的總數。
P1892 可以說是這題的弱化版,P1892 只涉及了兩個關係,只要弄一個虛點就行,而且最主要的差別是:P1892 朋友的敵人不一定是我的敵人,所以當確定兩個人是朋友關係時,只要把 x 和 y 放在一起,不要涉及 x+n 和 y+n 這兩個虛點;
但是這題就不一樣了,不僅多加一個虛點表示被吃關係,而且當 x 和 y 是同類時(也可以說是朋友),x+n 和 y+n 要關聯在一起,x+2n 和 y+2n 也要關聯在一起,也就是說朋友的敵人一定是我的敵人,朋友的獵物一定是我的獵物;
還有當 x 吃 y 時,不僅要表示 x 和 y 的吃與被吃關係,還要表示 y 的獵物是 x 的天敵這層關係,具體表現就是 x+2n 和 y+n 關聯在一起;
代碼:
#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,int>
#define ls k<<1
#define rs k<<1|1
#define inf 0x3f3f3f3f
using namespace std;
const int N=500100;
const int M=50100;
const int mod=1e9;
int n,k,fa[N];
int find(int p){
if(p==fa[p]) return p;
return fa[p]=find(fa[p]);
}
int main(){
cin>>n>>k;
for(int i=1;i<=4*n;i++) fa[i]=i;
int ans=0;
for(int i=1;i<=k;i++){
int op,x,y;cin>>op>>x>>y;
if(x>n||y>n){
ans++;
continue;
}
if(op==1){
if(find(x)==find(y+n)||find(x+n)==find(y)) ans++;
else if(find(x)==find(y+2*n)||find(x+2*n)==find(y)) ans++;
else{
fa[find(x)]=find(y);
fa[find(x+n)]=find(y+n);
fa[find(x+2*n)]=find(y+2*n);
}
}
else{
if(x==y) ans++;
else{
if(find(x)==find(y)) ans++;
else if(find(x)==find(y+n)||find(x+2*n)==find(y)) ans++;
else{
fa[find(x)]=find(y+2*n);
fa[find(y)]=find(x+n);
fa[find(x+2*n)]=find(y+n);
}
}
}
}
cout<<ans<<endl;
return 0;
}