#include <iostream>
#include <vector>
#include <utility>
#include <queue>

using namespace std;

const long long int INF=1e9;

struct road{
    int id;
    long long int cost;
};

int main() {
    int N, M;
    cin >> N >> M;
    
    vector<vector<road> > R(N+1, vector<road>(N+1, {-1, INF}));
    vector<vector<int> > Rv(N+1, vector<int>());
    for(int m=0; m<M; m++) {
        int a, b;
        long long int c;
        cin >> a >> b >> c;
        R[a][b] = {m, c};
        R[b][a] = {m, c};
        Rv[a].push_back(b);
        Rv[b].push_back(a);
    }
    
    vector<bool> road_used(M, false);
    
    vector<bool> vertex_seen(N+1, false);
    vector<long long int> cost_from_s(N+1, INF);
    vector<vector<int> > used_road_from_s(N+1, vector<int>());
    auto cmp = [](pair<int, long long int> x, pair<int, long long int> y) {
        if(x.second != y.second) {
            return x.second > y.second;
        } else {
            return x.first < y.first;
        }
    };
    
    for(int s=1; s<=N-1; s++) {
        vertex_seen = vector<bool>(N+1, false);
        cost_from_s = vector<long long int>(N+1, INF);
        cost_from_s[s] = 0;
        priority_queue<pair<int, long long int>, vector<pair<int, long long int> >\
    , decltype(cmp)> que(cmp);
        que.push(make_pair(s, 0));
        
        for(int e=s+1; e<=N; e++) {
            // cout << "from " << s << " target " << e << endl;

            if(vertex_seen[e]) {
                // cout << "since target " << e << " is already seen" << endl;
                
                for(int ui=0; ui<used_road_from_s[e].size(); ui++) {
                    road_used[used_road_from_s[e][ui]] = true;
                }
                
                continue;
            }

            while(!que.empty()) {
                int cur_v=que.top().first;
                    que.pop();
                while(vertex_seen[cur_v]) {
                    cur_v=que.top().first;
                    que.pop();
                }

                // cout << "cur_v is " << cur_v << endl;
                
                for(int rvi=0; rvi<Rv[cur_v].size(); rvi++) {
                    int next_v=Rv[cur_v][rvi];
                    if(vertex_seen[next_v]) {
                        continue;
                    } else {
                        // cout << "next_v is " << next_v << endl;
                        if(cost_from_s[next_v]>cost_from_s[cur_v]+R[cur_v][next_v].cost) {
                            cost_from_s[next_v] = cost_from_s[cur_v]+R[cur_v][next_v].cost;
                            used_road_from_s[next_v] = used_road_from_s[cur_v];
                            used_road_from_s[next_v].push_back(R[cur_v][next_v].id);
                            que.push(make_pair(next_v, cost_from_s[next_v]));
                        }
                    }
                }

                vertex_seen[cur_v] = true;
                if(vertex_seen[e]) {
                    for(int ui=0; ui<used_road_from_s[e].size(); ui++) {
                        road_used[used_road_from_s[e][ui]] = true;
                    }
                    break;
                }
            }
        }
    }

    int count=0;
    for(int m=0; m<M; m++) {
        if(road_used[m]) continue;
        count++;
    }
    
    cout << count << endl;

    return 0;
    
}

Measured memory_bytes: 768