#include using namespace std; const int MAXN = 1e5 + 5; vector> G[MAXN], Gt[MAXN]; vector Gr[MAXN]; int Viz[MAXN], Color[MAXN], Rep[MAXN], Bad[MAXN]; long long LB[MAXN]; long long Dist[MAXN]; int inQ[MAXN], Count[MAXN]; int cc, n; vector St; void dfsK1(int node) { Viz[node] = 1; for(auto vec : G[node]) { if(!Viz[vec.first]) dfsK1(vec.first); } St.push_back(node); } void dfsK2(int node) { Viz[node] = 2; Color[node] = cc; Count[cc] += 1; Rep[cc] = node; // cerr << node << " "; for(auto vec : Gt[node]) { if(Viz[vec.first] < 2) { dfsK2(vec.first); if(vec.second < 0) LB[cc] += vec.second; } } // cerr << endl; } void Kosaraju() { for(int i=1; i<=n; i++) if(Viz[i] == 0) dfsK1(i); for(int i=St.size()-1; i>=0; i--) if(Viz[St[i]] == 1) { cc++; // cerr << cc << ": "; dfsK2(St[i]); } } void dfsK3(int node) { Viz[node] = 3; for(auto vec : Gr[node]) { if(Viz[vec] < 3) { dfsK3(vec); Bad[node] = max(Bad[node], Bad[vec]); } } } queue Q; int Bellman(int start) { int now_cc = Color[start]; if(now_cc == 1) cerr << "x"; Dist[start] = 0; Q.push(start); while(!Q.empty()) { int node = Q.front(); Q.pop(); inQ[node] = 0; for(auto vec : G[node]) { if(Color[vec.first] == now_cc && Dist[vec.first] > Dist[node] + vec.second) { Dist[vec.first] = Dist[node] + vec.second; if(Dist[vec.first] < LB[now_cc]) return 1; if(!inQ[vec.first]) { Q.push(vec.first); inQ[vec.first] = 1; } } } } return 0; } int main() { #ifndef ONLINE_JUDGE freopen("debug", "r", stdin); #endif // ONLINE_JUDGE int m, a, b, c; cin >> n >> m; while(m--) { cin >> a >> b >> c; G[a].push_back({b, c}); Gt[b].push_back({a, c}); } Kosaraju(); for(int i=1; i<=n; i++) Dist[i] = 1e9; for(int i=1; i<=cc; i++) { Bad[i] = Bellman(Rep[i]); } for(int i=1; i<=n; i++) { for(auto vec : G[i]) { Gr[Color[i]].push_back(Color[vec.first]); } } int ans = 0; for(int i=1; i<=cc; i++) { if(Viz[i] < 3) { dfsK3(i); // cerr << Count[i] << " " << Bad[i] << '\n'; } ans += Count[i] * Bad[i]; } cout << ans; return 0; }