方法一:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
const int maxn=50010;
int pra[maxn],rank[maxn];
int n,k;
void init()
{
for(int i=0;i<=n;i++)
{
pra[i]=i;
rank[i]=0;
}
}
int find(int x)
{
if(x!=pra[x])
{
int f=find(pra[x]);
rank[x]=(rank[x]+rank[pra[x]])%3;
pra[x]=f;
}
return pra[x];
}
bool unite(int x,int y,int d)
{
int fx=find(x);
int fy=find(y);
if(fx==fy)
{
if((rank[y]-rank[x]+3)%3!=d)return true;
else return false;
}
pra[fy]=fx;
rank[fy]=(rank[x]-rank[y]+d+3)%3;
return false;
}
int main()
{
//freopen("in.txt","r",stdin);
int x,y,d,ans;
scanf("%d%d",&n,&k);
init();
ans=0;
for(int i=0;i<k;i++)
{
scanf("%d%d%d",&d,&x,&y);
if(x>n||y>n||(d==2)&&x==y){ans++;continue;}
if(unite(x,y,d-1))ans++;
}
printf("%d\n",ans);
return 0;
}
方法二:
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=100005;
int t[maxn],x[maxn],y[maxn];
int pre[150010],rank[150010];
int N,K;
int find1(int x)
{
if(pre[x]==x)
return x;
return pre[x]=find1(pre[x]);
}
bool same(int x,int y)
{
return find1(x)==find1(y);
}
void unite(int x,int y)
{
x=find1(x);
y=find1(y);
if(x==y)
return;
pre[x]=y;
}
void slove()
{
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||X>=N||Y<0||Y>=N)
{
ans++;
continue;
}
if(T==1)
{
if(same(X,Y+N)||same(X,Y+2*N))
ans++;
else
{
unite(X,Y);
unite(X+N,Y+N);
unite(X+N*2,Y+N*2);
}
}
else
{
if(same(X,Y)||same(X,Y+N*2))
ans++;
else
{
unite(X,Y+N);
unite(X+N,Y+N*2);
unite(X+N*2,Y);
}
}
}
cout<<ans<<endl;
}
int main()
{
//freopen("in.txt","r",stdin);
cin>>N>>K;
for(int i=0; i<K; i++)
scanf("%d%d%d",&t[i],&x[i],&y[i]);
for(int i=0; i<N*3; i++)
pre[i]=i;
slove();
return 0;
}