#include<stdio.h>
const int Maxn=50002;
int n,m,num;
int pre[Maxn];
int offset[Maxn];
void initial()
{
for(int i=1;i<=n;i++)
{
pre[i]=-1;
offset[i]=0;
}
}
int find(int x)
{
if(pre[x]<0) return x;
int temp=pre[x];
pre[x]=find(temp);
offset[x]=(offset[x]+offset[temp])%3;
return pre[x];
}
void merge(int d,int x,int y)
{
if(x>n||y>n)
{
num++;
}
else
{
if(d==1)
{
int root1=find(x),root2=find(y);
if(root1==root2) //一旦属于同一个集合,就需需要判断是否为谎言,否则只需合并集合
{
if(offset[x]!=offset[y]) num++;
}
else
{
if(pre[root1]<pre[root2])
{
pre[root1]=pre[root1]+pre[root2];
pre[root2]=root1;
offset[root2]=(offset[x]-offset[y]+3)%3;
}
else
{
pre[root2]=pre[root2]+pre[root1];
pre[root1]=root2;
offset[root1]=(offset[y]-offset[x]+3)%3;
}
}
}
else
{
if(x==y) num++;
else //x吃y->offset[y]=offset[x]+1;
{
int root1=find(x),root2=find(y);
if(root1==root2)
{
if(offset[y]!=(offset[x]+1)%3) num++;
}
else
{
if(pre[root1]<pre[root2])
{
pre[root1]=pre[root1]+pre[root2];
pre[root2]=root1;
offset[root2]=(offset[x]+1-offset[y]+3)%3;
}
else
{
pre[root2]=pre[root2]+pre[root1];
pre[root1]=root2;
offset[root1]=(offset[y]-1-offset[x]+3)%3;
}
}
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
int d,x,y;
initial();
while(m--)
{
scanf("%d%d%d",&d,&x,&y);
merge(d,x,y);
}
printf("%d\n",num);
return 0;
}
|