AcWing 240. 食物链
原题链接
中等
作者:
RealDish
,
2020-09-17 00:03:42
,
所有人可见
,
阅读 408
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 200010;
int food[N], n, k, d, x, y;
//并查集数组为food[N],f[0 ~ n]为同类域,f[n ~ 2*n]为捕食域,f[2*n ~ 3 * n]为天敌域
void init_set(){
//并查集的初始化
for(int i = 0; i <= 3 * n; i++)
food[i] = i;
}
int find_set(int x){
//并查集查询与路径压缩
return x == food[x] ? x : food[x] = find_set(food[x]);
}
void merge_set(int x, int y){
//查询x, y集合的祖宗
x = find_set(x);
y = find_set(y);
if( x == y )return ;
food[x] = y;//若不为一个集合则合并
}
int main(){
cin >> n >> k;
int ans = 0;//记录假话个数
init_set();//初始化并查集
for(int i = 1; i <= k; i++){
cin >> d >> x >> y;
//若当前的话中X或Y比N大,就是假话。
if(x > n || y > n || x < 1 || y < 1)ans++;
else if(d == 1){
//即当x , y有捕食关系与x, y是同类冲突,所以是假话
if( find_set(x) == find_set(y + n) || find_set(x) == find_set(y + 2 * n) )ans++;
else{
merge_set(x, y);//合并x, y的同类域
merge_set(x + n, y + n);//合并x, y的捕食域
merge_set(x + 2 * n , y + 2 * n);//合并x, y的天敌域
}
}else{
//当x == y时自己吃自己或者x, y是同类、y吃x——与当前x吃y矛盾,所以是假话
if( x == y || find_set(x) == find_set(y) || find_set(x) == find_set(y + n)){
ans++;
}else{
merge_set(x, y + 2 * n);//x的同类域与y的天敌域合并
merge_set(x + n, y);//x的捕食域与y的同类域合并
merge_set(x + 2 * n , y + n);//x的天敌域与y的捕食域合并
}
}
}
cout << ans << endl;
return 0 ;
}