题目链接
题意
草原上有ABC三种动物,A吃B,B吃C,C吃A。编号1-n的n个动物,给定两个个体之间的关系,判断有几条关系是错误的。
思路
因为n个动物都是属于三种动物之一,那么可以做出如下判断:
- 当a,b动物是同类时,他们的食物都是同类,他们的天敌也是同类
- 当a吃b时,a的食物和b都是同类,a的天敌和b的食物都是同类,a和b的天敌都是同类。
于是我们可以开一个三倍大小的并查集,1-n代表动物们自己,2-n代表各个动物的食物,2n-3n就是他们的天敌。
那么关系给出ab是同类时,只要判断一下b和a的天敌是否是同类,b和a的食物是否是同类就可以判断是否正确。正确的话将a和b,a+n和b+n,a+2n和b+2n连接。
对于给出a吃b的关系,那么我们判断一下a和b是不是同类,a的天敌和b是不是同类即可,对于正确的,将a+n和b,a+2*n和b+n,a和b+2n连接即可。
代码
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
using namespace std;
typedef long long ll;
const int maxn=160000;
const int inf=0x3f3f3f3f;
int fa[maxn];
int ra[maxn];
void init(){
for(int i=0;i<maxn;i++){
fa[i]=i;
ra[i]=0;
}
return ;
}
int find(int x){
return x==fa[x]?x:fa[x]=find(fa[x]);
}
void unite(int x,int y){
x=find(x); y=find(y);
if(x==y)
return ;
else if(ra[x]<ra[y]){
fa[x]=y;
}
else{
fa[y]=x;
if(ra[x]==ra[y])
ra[x]++;
}
}
int main(){
init();
int n,k;
scanf("%d%d",&n,&k);
int ans=0;
while(k--){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(b>n||c>n||b<1||c<1){
ans++;
continue;
}
if(a==1){
if(find(c+n)==find(b)||find(c+2*n)==find(b)){
ans++;
continue;
}
unite(b,c);
unite(b+n,c+n);
unite(b+2*n,c+2*n);
}
else{
if(b==c||find(b)==find(c)||find(b+2*n)==find(c)){
ans++;
continue;
}
unite(b+n,c);
unite(b+2*n,c+n);
unite(b,c+2*n);
}
}
printf("%d\n",ans);
}