#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=100005;
const int M=600005; // 会建两边图
int n, m, E=0;
int h[N], hs[N];
int dfn[N], low[N], id[N], sz[N], ts=0; // tarjan
bool vis[N];
stack<int> st;
int scc_cnt=0;
int dist[N];
struct Edge{int v, ne, w;}e[M];
inline void add(int h[], int a, int b, int c){
e[E].v=b;
e[E].w=c;
e[E].ne=h[a];
h[a]=E++;
}
void tarjan(int u){
dfn[u]=low[u]=++ts;
st.push(u); vis[u]=true;
for(int i=h[u]; ~i; i=e[i].ne){
int v=e[i].v;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u], low[v]);
}
else if(vis[v]){
low[u]=min(low[u], dfn[v]);
}
}
if(low[u]==dfn[u]){
++scc_cnt;
int j;
do{
j=st.top(); st.pop(); vis[j]=false;
id[j]=scc_cnt;
sz[scc_cnt]++;
}while(j!=u);
}
}
int main(){
cin>>n>>m;
memset(h, -1, sizeof h);
memset(hs, -1, sizeof hs);
memset(vis, 0x00, sizeof vis);
memset(dist, 0x00, sizeof dist);
// 建立超级源点(xi>=1)
for(int i=1; i<=n; ++i) add(h, 0, i, 1);
while(m--){
int t, a, b;
cin>>t>>a>>b;
if(t==1) {add(h, b, a, 0); add(h, a, b, 0);} // xa=xb
else if(t==2) add(h, a, b, 1); // xa<xb
else if(t==3) add(h, b, a, 0); // xa>=xb
else if(t==4) add(h, b, a, 1); // xa>xb
else if(t==5) add(h, a, b, 0); // xa<=xb
}
tarjan(0);
// 缩点
bool flag=true;
for(int i=0; i<=n; ++i){
for(int j=h[i]; ~j; j=e[j].ne){
int v=e[j].v;
int a=id[i], b=id[v];
if(a==b){ // 如果在一个scc中权值应该为0
if(e[j].w>0){flag=false; break;}
}
else add(hs, a, b, e[j].w);
}
if(!flag) break;
}
if(!flag) cout<<-1<<endl;
else{
for(int i=scc_cnt; i; --i){
for(int j=hs[i]; ~j; j=e[j].ne){
int v=e[j].v;
dist[v]=max(dist[v], dist[i]+e[j].w);
}
}
LL ans=0;
for(int i=1; i<=scc_cnt; ++i) ans+=(LL)dist[i]*sz[i];
cout<<ans<<endl;
}
return 0;
}