//首先重新定义题目中的关系,A与B的关系是0代表A与B同类。1代表A吃B,2代表B吃A
//也就是题目中的d-1
//利用传递性,A与B的关系和B与C的关系推出A与C的关系
// A与B B与C A与C
// 0 0 0
// 0 1 1
// 0 2 2
// 1 0 1
// 1 1 2
// 1 2 0
// 2 0 2
// 2 1 0
// 2 2 1
//立即推得A与C的关系=(A与B的关系+B与C的关系)%3
//接着需要写一个check函数,用来检查他们说的话是不是真的
//有题目可知false的情况,然后寻找出他们的祖宗,如果不是同一个祖宗说明还没有
//建立关系,就先认为是真的
//如果已经建立关系(!!),就需要判断A和B的关系,我们可以借助A与祖宗的关系以及B与
//祖宗的关系推出A与B的关系
//A与根 B与根 A与B
//0 0 0
//0 1 2
//0 2 1
//1 0 1
//1 1 0
//1 2 2
//2 0 2
//2 1 1
//2 2 0
//可推得A与B的关系=(A与根的关系-B与根的关系+3)%3 为了防止取余时负数所以+3
//再判断是否与给定的d-1相等,相等就是真的,不相等就时假的
//如果为真我们需要合并两个集合,所以最后要重新写unite(union)函数
//把x的跟指向y的根,所以需要x的根与y的根的关系
//由于A和A的根的关系已知,A和B的关系已知(题目给的),B和根的关系已知
//如果知道A的根与A的关系就可以由A的根->A->B->B的根
//A与A的根 A的根与A
//0 0
//1 2
//2 1
//推得根与A的关系=(3-A与根的关系)
//A与B的关系为d-1
//又因为A与C的关系=(A与B的关系+B与C的关系)%3
//推得A的根与B的关系=(A的根与A的关系+A的B的关系)%3
//B与B的根的关系已知
//推得A的根与B的根的关系=((A的根与A的关系+A与B的关系)%3+B与B的根的关系)%3
//=(3-A与A的根+A与B的关系+B与B的根的关系)%3
#include<iostream>
const int maxN=50001;
int parent[maxN],parentRelation[maxN],n;
int find(int x){
if(parent[x]==x)return x;
int root=find(parent[x]);//找到根
parentRelation[x]=(parentRelation[x]+parentRelation[parent[x]])%3;
return parent[x]=root;//压缩路径
}
bool check(int d,int x,int y){
if(x>n||y>n)return false;
if(d==2&&x==y)return false;
int a=find(x),b=find(y);
if(a!=b)return true;
return (parentRelation[x]-parentRelation[y]+3)%3==d-1;
}
void unite(int d,int x,int y){
//将x的根连接到y的根上
int a=find(x),b=find(y);
if(a==b)return;
parent[a]=b;
parentRelation[a]=(3-parentRelation[x]+(d-1)+parentRelation[y])%3;
}
int main(){
int k,d,a,b,ans;
scanf("%d%d",&n,&k);
ans=0;
for(int i=1;i<=n;++i){
parent[i]=i;
parentRelation[i]=0;
}
while(k--){
scanf("%d%d%d",&d,&a,&b);
if(check(d,a,b))unite(d,a,b);
else ++ans;
}
printf("%d\n",ans);
return 0;
}