//并查集
//
//查询 是否在同一个组
//合并 这两个组
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=100;
int head[N];
int rank[N];
void init(int n){
for(int i=0;i<=n;i++){
head[i]=i;
rank[i]=0;
}
}
int find(int x){
if(head[x]==x)return x;
return head[x]=find(head[x]);//找根
//路径压缩:最终的根给当前的x 这样一路上的点全都直接连在根下面了
}
void unite(int x,int y){
x=find(x);
y=find(y);
if(x==y)return;
if(rank[x]<rank[y])
head[x]=y;
else{
head[y]=x;
if(rank[x]==rank[y]) rank[x]++;
} //两个树一长一短 短的去连在长的下面
}//要是一样长 那y连到x x长度要++。 防止越来越长 成链 增加复杂度
bool same(int x,int y)
{
return find(x)==find(y);
}
/*
食物链 POJ 1182
N个动物 三种 A吃B B吃C C吃A
K条信息
第一种信息 a b是同一种动物
第二种信息 a吃b
有的信息错误(不存在这个动物or与之前矛盾or出错)
//A 1 2:表示1和2是同一种 那么若1是A,2是A 并查集合并 若B若C同理
//B 1 2:表示1吃2 若1是A,2是B 并查集合并 若B若C同理
//0~n-1 表示i是A
//n~2*n 表示i是B
//2n~3n 表示i是C
int main()
{
int n,k,ans=0;
cin>>n>>k;
init(3*n);
while(k--){
char x;
int a,b;
cin>>x>>a>>b;
a=a--;
b=b--;
if(a<0||b<0||a>=n||b>=n){
ans++;
continue;
}
if(x=='A'){//a b同一类
if(same(a,b+n)||same(a,b+2*n))//矛盾:如果x是A而y是B或者C
ans++;
else
{
unite(a,b);//若x是A种 那y就也是A种
unite(n+a,n+b);
unite(n*2+a,n*2+b);
}
}
else{
if(same(a,b)||same(a,b+n*2))ans++;
else
{
unite(a,b+n);
unite(a+n,b+n*2);
unite(a+n*2,b);
}
}
}
cout<<ans<<endl;
return 0;
}
/*
样例输入
100 7
A 101 1
B 1 2
B 2 3
B 3 3
A 1 3
B 3 1
A 5 5
输出
3
*/