#include using namespace std; ///--------------------------------------------------- const int BUFFER_SIZE = (1 << 16); char buffer[BUFFER_SIZE]; int position = BUFFER_SIZE; inline char getChar() { if ( position == BUFFER_SIZE ) { position = 0; fread(buffer, BUFFER_SIZE, 1, stdin); } return buffer[position++]; } inline int getInt() { register int a = 0; char ch; int sgn = 1; do { ch = getChar(); } while ( !isdigit(ch) && ch != '-' ); if ( ch == '-' ) { sgn = -1; ch = getChar(); } do { a = (a << 3) + (a << 1) + ch - '0'; ch = getChar(); } while ( isdigit(ch) ); return a * sgn; } ///--------------------------------------------------- const int MAX_N = 100000 + 1; const long long INF = numeric_limits::max() / 2; vector> G[MAX_N]; vector> GT[MAX_N]; bool checked[MAX_N]; bool visited[MAX_N]; bool inQueue[MAX_N]; long long dist[MAX_N]; int accessed[MAX_N]; queue Q; int N, M; void dfs(int node) { inQueue[node] = false; dist[node] = INF; accessed[node] = 0; visited[node] = true; for (pair v : G[node]) if (!visited[v.first]) dfs(v.first); } int bellmanFord(int node) { dfs(node); Q.push(node); inQueue[node] = true; dist[node] = 0; accessed[node] = 0; while (Q.empty() == false) { int nod = Q.front(); Q.pop(); inQueue[nod] = false; accessed[nod]++; if (accessed[nod] >= N) return nod; for (pair pii : G[nod]) { int v = pii.first; int c = pii.second; if (dist[v] > dist[nod] + c) { dist[v] = dist[nod] + c; if (!inQueue[v]) { inQueue[v] = true; Q.push(v); } } } } return 0; } void dfsT(int node, int &solution) { checked[node] = true; solution++; for (pair pii : GT[node]) if (!checked[pii.first]) dfsT(pii.first, solution); } int main() { ///freopen("data.in", "r", stdin); N = getInt(); M = getInt(); for (int i = 1; i <= M; ++i) { int a, b, c; a = getInt(); b = getInt(); c = getInt(); G[a].push_back({b, c}); GT[b].push_back({a, c}); } int solution = 0; for (int i = 1; i <= N; ++i) if (!checked[i] && !visited[i]) { int node = bellmanFord(i); if (node > 0) dfsT(node, solution); } cout << solution << "\n"; return 0; }