3
对于每个元素都设三种可能,可能是A,B,C中的随意一种,所以能够开一个N*3大的数组进行保存
/*
Author: 2486
Memory: 2292 KB Time: 266 MS
Language: G++ Result: Accepted
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=50000+5;
int N,K;
int T[100000+5],X[100000+5],Y[100000+5];
//T代表着是那种操作
//X,Y代表两个编号
int par[maxn*3],ranks[maxn*3];
void init(int m) {
for(int i=0; i<=m; i++) {
par[i]=i;
ranks[i]=0;
}
}
int find(int x) {
return par[x]==x?x:par[x]=find(par[x]);
}
bool same(int x,int y) {
return find(x)==find(y);
}
void unite(int x,int y) {
x=find(x);
y=find(y);
if(x==y)return;
if(ranks[x]<ranks[y]) {
par[x]=y;
} else {
par[y]=x;
if(ranks[x]==ranks[y])ranks[x]++;
}
}
void solve() {
init(N*3);
int ans=0;
for(int i=0; i<K; i++) {
int t=T[i];
int x=X[i]-1,y=Y[i]-1;
if(x<0||N<=x||y<0||N<=y) {
ans++;
continue;
}
if(t==1) {
//假设是一,那么就要推断是否为同一类型不能冲突
//首先将x定为A。由于无论是B,C也好。都不影响题目结果
//假设你设定为B,到最后的结果。将A与B兑换一下,结果与设定为A一样
//第一个推断表示假设x->A,y->B。假设为同一类型,冲突
//第二个推断表示假设x->A,y->C假设为同一类型,冲突
if(same(x,y+N)||same(x,y+2*N)) {
ans++;
} else {
unite(x,y);//假设他们是A类型。则连接A
unite(x+N,y+N);//假设他们是B类型,则连接B
unite(x+2*N,y+2*N);//假设他们是B类型。则连接B
}
} else {
//假设为同一类型的话,是不可以为同一类型的
//同一时候必须是A->B,B->C,C->A
if(same(x,y)||same(x,y+2*N)) {
ans++;
} else {
unite(x,y+N);//假设x是A类型y是B类型,A->B
unite(x+N,y+2*N);//假设x是B类型y是C类型,B->C
unite(x+2*N,y);//假设x是C类型y是A类型,C->A
}
}
}
printf("%d\n",ans);
}
int main() {
scanf("%d%d",&N,&K);
for(int i=0; i<K; i++) {
scanf("%d%d%d",&T[i],&X[i],&Y[i]);
}
solve();
return 0;
}