// P3275 糖果。迭代 Kosaraju + 缩点 DAG 上的最长下界,O(n+k)。 #include using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, k; if (!(cin >> n >> k)) return 0; vector>> g(n); vector> rg(n); auto add = [&](int u, int v, int w) { g[u].push_back({v,w}); rg[v].push_back(u); }; for (int i = 0, x, a, b; i < k; ++i) { cin >> x >> a >> b; --a; --b; if (x == 1) { add(a,b,0); add(b,a,0); } if (x == 2) add(a,b,1); if (x == 3) add(b,a,0); if (x == 4) add(b,a,1); if (x == 5) add(a,b,0); } vector vis(n, false); vector order; // 第一次 DFS:显式保存下一条边下标,退出时记录结束序。 for (int s = 0; s < n; ++s) if (!vis[s]) { vector> st; vis[s] = true; st.push_back({s,0}); while (!st.empty()) { auto &[u,i] = st.back(); if (i == (int)g[u].size()) { order.push_back(u); st.pop_back(); } else { int v = g[u][i++].first; if (!vis[v]) { vis[v] = true; st.push_back({v,0}); } } } } // 第二次 DFS:反图按逆结束序分组。 vector comp(n, -1), size; int count = 0; reverse(order.begin(), order.end()); for (int s : order) if (comp[s] == -1) { vector st(1,s); comp[s] = count; int amount = 0; while (!st.empty()) { int u = st.back(); st.pop_back(); ++amount; for (int v : rg[u]) if (comp[v] == -1) { comp[v] = count; st.push_back(v); } } size.push_back(amount); ++count; } vector>> dag(count); vector indeg(count, 0), d(count, 1); for (int u = 0; u < n; ++u) for (auto [v,w] : g[u]) { if (comp[u] == comp[v]) { if (w == 1) { cout << -1 << '\n'; return 0; } } else { dag[comp[u]].push_back({comp[v],w}); ++indeg[comp[v]]; } } queue q; for (int c = 0; c < count; ++c) if (indeg[c] == 0) q.push(c); while (!q.empty()) { int u = q.front(); q.pop(); for (auto [v,w] : dag[u]) { d[v] = max(d[v], d[u]+w); if (--indeg[v] == 0) q.push(v); } } long long ans = 0; for (int c = 0; c < count; ++c) ans += 1LL * size[c] * d[c]; cout << ans << '\n'; }