并查集
一道非常经典的并查集题目。分三个集合,x+n为x所吃的集合,x+2n为吃x的集合。然后不断合并即可。
合并的时候三个集合都要合并。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 50000
using namespace std;
int n,k;
int fa[MAXN*3+5];
char readc(){
static char buf[100000],*l=buf,*r=buf;
if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
if (l==r) return EOF;
return *l++;
}
inline int _read(){
char ch=readc(); int num=0;
while (ch<'0'||ch>'9') ch=readc();
while (ch>='0'&&ch<='9') { num=num*10+ch-48; ch=readc(); }
return num;
}
int findfather(int x){
if (fa[x]==x) return fa[x];
return fa[x]=findfather(fa[x]);
}
bool judge1(int x,int y){
if (findfather(x+n)==findfather(y)||findfather(x+2*n)==findfather(y)) return false;
return true;
}
bool judge2(int x,int y){
if (findfather(x)==findfather(y)||findfather(x+2*n)==findfather(y)) return false;
return true;
}
void mix(int x,int y){
fa[findfather(x)]=findfather(y);
}
int main(){
n=_read(); k=_read();
for (int i=1;i<=3*n;i++) fa[i]=i;
int ans=0;
while (k--){
int flag=_read(),x=_read(),y=_read();
if (x>n||y>n){ ans++; continue; }
if (flag==1)
if (judge1(x,y)){
mix(x,y);
mix(x+n,y+n);
mix(x+2*n,y+2*n);
}
else ans++;
if (flag==2){
if (x==y){ ans++; continue; }
if (judge2(x,y)){
mix(x+n,y);
mix(x+2*n,y+n);
mix(x,y+2*n);
}
else ans++;
}
}
printf("%d\n",ans);
return 0;
}