#include <iostream>
using namespace std;
const int maxN = 5e4 + 5;
int n = 0, k = 0, ans = 0;
struct Sentences
{
int type, a, b;
} sentence;
class UnionFindSet
{
public:
inline void initialization(int a) { s[a] = a; }
int lookfor(int a)
{
if (a != s[a]) s[a] = lookfor(s[a]);
return s[a];
}
void unionset(int a, int b, int type)
{
switch (type)
{
case 1:
mergeset(a, b);
mergeset(a + n, b + n);
mergeset(a + (2 * n), b + (2 * n));
case 2:
mergeset(a, b + (2 * n));
mergeset(a + n, b);
mergeset(a + (2 * n), b + n);
}
}
private:
int s[3 * maxN]{};
void mergeset(int a, int b)
{
a = lookfor(a); b = lookfor(b);
s[a] = (a == b ? s[a] : b);
}
};
int main()
{
UnionFindSet ufs;
cin >> n >> k;
for(int i = 0; i < 3 * n; i++) ufs.initialization(i);
while(k--)
{
cin >> sentence.type >> sentence.a >> sentence.b;
if (sentence.a > n || sentence.b > n) { ans++; continue; }
switch (sentence.type)
{
case 1:
if (ufs.lookfor(sentence.a) == ufs.lookfor(sentence.b)) break;
if (ufs.lookfor(sentence.a) == ufs.lookfor(sentence.b + n)) { ans++; break; }
if (ufs.lookfor(sentence.a) == ufs.lookfor(sentence.b + (2 * n))) { ans++; break; }
ufs.unionset(sentence.a, sentence.b, sentence.type); break;
case 2:
if (ufs.lookfor(sentence.a) == ufs.lookfor(sentence.b + (2 * n))) break;
if (ufs.lookfor(sentence.a) == ufs.lookfor(sentence.b)) { ans++; break; }
if (ufs.lookfor(sentence.a) == ufs.lookfor(sentence.b + n)) { ans++; break; }
ufs.unionset(sentence.a, sentence.b, sentence.type); break;
default:
break;
}
}
cout << ans << endl;
return 0;
}