#include <bits/stdc++.h>
#define Nmax 200005
#define INF 0x3f3f3f3f
using namespace std;

vector<pair<int,int> > G[Nmax];
vector<int> Gt[Nmax],SCC[Nmax],SCCT[Nmax],order;
bitset<Nmax>used,inQ;
stack<int> S;
queue<int> Q;
int N,M,scc[Nmax],nrc,bune[Nmax],ciclu[Nmax],OUT[Nmax];
int DP[Nmax];
int Size[Nmax],NRQ[Nmax];

void Read()
{
    scanf("%d%d",&N,&M);
    int a,b,c;
    for(int i = 1; i <= M; ++i)
    {
        scanf("%d%d%d",&a,&b,&c);
        G[a].push_back({c,b});
        Gt[b].push_back(a);
    }

    order.resize(N);
    for(int i = 1; i <= N; ++i)
        order[i-1] = i;
    random_shuffle(order.begin(),order.end());
    for(int i = 1; i <= N; ++i)
        if(G[i].size())
            random_shuffle(G[i].begin(),G[i].end());
}

void DFS(int k){
    used[k] = 1;
    for(auto it : G[k])
        if(!used[it.second])
            DFS(it.second);
    S.push(k);
}

void DFST(int k){
    used[k] = 1;
    scc[k] = nrc; /// k apartine componentei tare conexe cu nr curent nrc
    Size[nrc]++;
    for(auto it : Gt[k])
        if(!used[it])
            DFST(it);
}

void Kosaraju()
{
    int k;
    for(int i = 1; i <= N; ++i)
        if(!used[i])
            DFS(i);
    used = 0;
    while(!S.empty())
    {
        k = S.top(); S.pop();
        if(used[k] == 1)
            continue;
        ++nrc;
        DFST(k);
    }
}

int Bellman_Ford(int k)
{
    int tip = scc[k];
    DP[k] = 0;
    Q.push(k);
    inQ[k] = 1;
    NRQ[k]++;

    while(!Q.empty())
    {
        k = Q.front();
        Q.pop();
        inQ[k] = false;

        for(auto it : G[k])
            if(scc[it.second] == tip && DP[it.second] > DP[k] + it.first)
            {
                DP[it.second] = DP[k] + it.first;
                if(inQ[it.second] == true)
                    continue;
                Q.push(it.second);
                inQ[it.second] = true;
                NRQ[it.second] ++;
                if(NRQ[it.second] > min(Size[tip],200))
                {
                    while(!Q.empty())
                        Q.pop();
                    return 1;
                }
            }
    }
    return 0;
}

void Get_Negative()
{

    memset(DP,INF,sizeof(DP));
    used = 0;
    int flag;
    for(int xx = 0; xx < N; ++xx){
        int i = xx + 1;///order[xx];
        if(!used[scc[i]]){
            used[scc[i]] = 1;
            flag = Bellman_Ford(i);
            if(flag == 1)
                ciclu[scc[i]] = 1;
        }
    }
}

void Build_Graph()
{
    int a,b;
    for(int i = 1; i <= N; ++i)
        for(auto it : G[i])
        {
            a = i;
            b = it.second;
            if(scc[a] == scc[b]) ///|| pusa[{scc[a],scc[b]}] == 1)
               continue;
            ///pusa[{scc[a],scc[b]}] = 1;
            ++OUT[scc[a]];
            SCC[scc[a]].push_back(scc[b]);
            SCCT[scc[b]].push_back(scc[a]);
        }

}

void Desfrunzire()
{
    for(int i = 1; i <= nrc; ++i)
        if(SCC[i].size() == 0 && ciclu[i] == 0)
            Q.push(i);
    int k = 0;
    while(!Q.empty())
    {
        k = Q.front();
        bune[k] = 1;
        Q.pop();
        for(auto it : SCCT[k])
        {
            OUT[it]--;
            if(OUT[it] == 0 && ciclu[it] == 0)
                Q.push(it);
        }
    }
    int cnt = 0;
    for(int i = 1; i <= N; ++i)
        if(bune[scc[i]] == 0)
            ++cnt;
    printf("%d\n",cnt);
}

int main()
{
    ///freopen("ciclu.in","r",stdin);
    ///freopen("ciclu.out","w",stdout);

    Read();
    Kosaraju();
    Get_Negative();
    Build_Graph();
    Desfrunzire();

    return 0;
}