#include #include #include #include using namespace std; const int MAX_N = 1e5 + 10; struct edge { int to; int cost; }; vector G[MAX_N]; bool viz[MAX_N]; int idx[MAX_N]; int low[MAX_N]; int deg[MAX_N]; long long DP[MAX_N]; int cnt[MAX_N]; bool hasCyc[MAX_N]; stack st; vector > comp; int belong[MAX_N]; void dfs(const int nod) { viz[nod] = 1; static int at = 1; idx[nod] = low[nod] = at; st.push(nod); at++; for(auto i: G[nod]) { int to = i.to; if(!viz[to]) dfs(to); if(low[to] < low[nod]) { low[nod] = low[to]; } } static int cat = 0; if(low[nod] == idx[nod]) { vector now; int x; do { x = st.top(); st.pop(); now.push_back(x); }while(x != nod); for(auto i: now) belong[i] = cat; comp.push_back(now); cat++; } } int n, m; void show(vector &i) { for(auto j: i) cerr << j << " "; cerr << "\n"; } void show(vector> & v) { for(auto i: v) { show(i); } } bool detect(const vector &v) { int st = v[0]; queue Q; Q.push(st); DP[st] = 0; bool fnd = 0; while(!Q.empty()) { int now = Q.front(); Q.pop(); cnt[now]++; if(cnt[now] >= m + 1) { return true; } for(auto e: G[now]) { int to = e.to, c = e.cost; if(belong[to] != belong[now]) continue; if(DP[now] + c < DP[to]) { DP[to] = DP[now] + c; Q.push(to); } } } return false; } bool cyc(int nod) { if(viz[nod]) return hasCyc[nod]; viz[nod] = 1; for(auto v: comp[nod]) { for(auto e: G[v]) { int to = belong[e.to]; if(cyc(to)) { hasCyc[nod] = 1; return 1; } } } return 0; } int main() { ios::sync_with_stdio(false); cin >> n >> m; for(int i = 1; i <= m; ++i) { int x, y, c; cin >> x >> y >> c; G[x].push_back((edge){y, c}); } for(int i = 1; i <= n; ++i) { if(viz[i]) continue; dfs(i); } for(int i = 1; i <= n; ++i) DP[i] = (1LL << 62); for(int i = 1; i <= n; ++i) { for(auto e: G[i]) { int to = e.to; deg[belong[to]]++; } } for(int i = 0; i < comp.size(); ++i) { hasCyc[i] = detect(comp[i]); } for(int i = 1; i <= n; ++i) viz[i] = 0; queue Q; for(int i = 0; i < comp.size(); ++i) { cyc(i); } int sol = 0; for(int i = 0; i < comp.size(); ++i) sol += hasCyc[i] * comp[i].size(); cout << sol << "\n"; return 0; }