#include using namespace std; typedef long long LL; const int N = 100010, M = 600010; int n, m; int h[N], hs[N], e[M], ne[M], w[M], idx; void add(int h[], int a, int b, int c) { e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++; } int dist[N]; // tarjan求scc int dfn[N], low[N], ts, stk[N], top, in_stk[N]; int id[N], scc_cnt, sz[N]; void tarjan(int u) { dfn[u] = low[u] = ++ts; stk[++top] = u; in_stk[u] = 1; for (int i = h[u]; ~i; i = ne[i]) { int v = e[i]; if (!dfn[v]) { tarjan(v); low[u] = min(low[u], low[v]); } else if (in_stk[v]) low[u] = min(low[u], dfn[v]); } if (dfn[u] == low[u]) { ++scc_cnt; int x; do { x = stk[top--]; in_stk[x] = 0; id[x] = scc_cnt; sz[scc_cnt]++; } while (x != u); } } int main() { scanf("%d %d", &n, &m); memset(h, -1, sizeof h); memset(hs, -1, sizeof hs); // 0号超级源点 // ∵ 恒星的亮度最暗是 1 // ∴ 0 ~ i 有一条边权为1的边 for (int i = 1; i <= n; i++) add(h, 0, i, 1); // 求最小->求所有下界的最大->最长路 √ while (m--) { int t, a, b; scanf("%d %d %d", &t, &a, &b); if (t == 1) // a=b add(h, b, a, 0), add(h, a, b, 0); else if (t == 2) // a < b --> b>=a+1 add(h, a, b, 1); else if (t == 3) // a>=b+0 add(h, b, a, 0); else if (t == 4) // a>=b+1 add(h, b, a, 1); else add(h, a, b, 0); // b>=a+0 } // 超级源点+强连通分量+缩点 tarjan(0); unordered_set S; // 对连着两个不同强连通分量的边进行判重 for (int u = 0; u <= n; u++) { // 添加上超级源点,就是n+1个点 for (int i = h[u]; ~i; i = ne[i]) { int v = e[i]; int a = id[u], b = id[v]; LL hash = a * 1000000ll + b; // 新两点a,b之间的Hash值,防止出现重边 if (a == b) { if (w[i] > 0) { // 在同一个强连通分量中,存在边权大于0的边 puts("-1"); // 必然有正环,最长路存在正环,原不等式组无解 exit(0); } } else if (!S.count(hash)) add(hs, a, b, w[i]); // 建新图 } } for (int u = scc_cnt; u; u--) // 倒序输出拓扑序 for (int i = hs[u]; ~i; i = ne[i]) { int v = e[i]; dist[v] = max(dist[v], dist[u] + w[i]); } // 因为不存在正环,而且题目保证都是路径>=0,所以强连通分量中必然路径长度都是0 // 即是一样一样的东西 LL res = 0; for (int i = 1; i <= scc_cnt; i++) res += (LL)dist[i] * sz[i]; printf("%lld\n", res); return 0; }