// RandomUsername (Nikola Jovanovic)
// MindCoding Round 2
// D

#include <bits/stdc++.h>
#define DBG false
#define debug(x) if(DBG) printf("(ln %d) %s = %d\n", __LINE__, #x, x);
#define lld long long
#define ff(i,a,b) for(int i=a; i<=b; i++)
#define fb(i,a,b) for(int i=a; i>=b; i--)
#define par pair<int, int>
#define fi first
#define se second
#define mid (l+r)/2
#define INF 1000000000
#define MAXN 100005

using namespace std;

struct node
{
    vector<lld> adj;
    vector<lld> w;
    bool OK;
    bool visited;
    lld iter;
    lld pathTo;
};

node g[MAXN];
lld n, m;
lld A, B, W;

lld currIter;

void DFS(lld curr, lld pathW)
{
    g[curr].iter = currIter;
    g[curr].visited = true;
    g[curr].pathTo = pathW;

    bool reachable = false;
    lld limit = g[curr].adj.size();
    ff(i, 0, limit - 1)
    {
        lld nxt = g[curr].adj[i];
        lld w = g[curr].w[i];
        if(!g[nxt].visited)
            DFS(nxt, pathW + w); // tree edge
        else if(g[nxt].iter == currIter && (pathW + w) - g[nxt].pathTo < 0)
            reachable = true; // back edge
        reachable |= g[nxt].OK; // cross edge
    }
    g[curr].OK = reachable;
}

int main()
{
    scanf("%lld %lld", &n, &m);
    ff(i, 1, m)
    {
        scanf("%lld %lld %lld", &A, &B, &W);
        g[A].adj.push_back(B);
        g[A].w.push_back(W);
    }
    currIter = 1;
    ff(i, 1, n)
    {
        if(!g[i].visited)
        {
            DFS(i, 0LL);
            currIter++;
        }
    }
    lld ret = 0LL;
    ff(i, 1, n)
    {
        ret += g[i].OK;
    }
    printf("%lld\n", ret);
    return 0;
}