传送门(洛谷)
此题和
\;\;
P1525 关押罪犯
\;\;
差不多,都是维护一个自己的反面。我们开一个三倍的并查集
x
x
x表示它自己
x
+
n
x+n
x+n表示它的天敌
x
+
2
∗
n
x+2*n
x+2∗n表示它的食物
如果
x
,
x
+
2
∗
n
,
x
+
n
x,x+2*n,x+n
x,x+2∗n,x+n任意两个在一个集合中都是不合法情况
#include<bits/stdc++.h>
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
using namespace std;
const int maxn=2e6+10;
const int maxm=2500+10;
int n,m,ans,cnt;
int f[maxn],head[maxn];
template <class t> inline void read(t &x) {
int f=1;x=0;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') ch=getchar();ch=getchar();}
while(isdigit(ch)){x=10*x+ch-'0';ch=getchar();}
x*=f;
}
inline int find(int x) {
if(f[x]==x) return x;
else return f[x]=find(f[x]);
}
inline void meger(int x,int y) {
int fx=find(x),fy=find(y);
f[fx]=fy;
}
void readdata() {
read(n);read(m);
rep(i,1,3*n) f[i]=i;
}
void work() {
rep(i,1,m) {
int flag,x,y;
read(flag),read(x),read(y);
if(x>n || y>n) {ans++;continue;}
if(flag==1) {
if(find(x+n)==find(y) || find(x+2*n)==find(y)) {ans++;continue;}
meger(x,y);meger(x+n,y+n);meger(x+2*n,y+2*n);
}
if(flag==2) {
if(x==y) {ans++;continue;}
if(find(x)==find(y) || find(x+n)==find(y)) {ans++;continue;}
meger(x+2*n,y);meger(x,y+n);meger(x+n,y+2*n);
}
}
printf("%d\n",ans);
}
int main() {
//freopen("input.txt","r",stdin);
freopen("test.in","r",stdin);
readdata();
work();
return 0;
}