#include<bits/stdc++.h>
#define REP(i,n) for(int i = 0;i < (n);i++)
#define P pair<int,int>
#define pb push_back
#define mk make_pair
using namespace std;
const int INF = 1e9;

typedef long long ll;

#define MAX_V 10000

struct edge {
    int to;
    int cost;
};


int V;
vector<edge> G[MAX_V];
int d[MAX_V];


void dijkstra(int s) {
    priority_queue<P, vector<P>, greater<P> > que;
    fill(d, d+V, INF);
    d[s] = 0;
    que.push(P(0, s));

    while (!que.empty()) {
        P p = que.top();
        que.pop();
        int v = p.second;
        if (d[v] < p.first) continue;

        for (int i=0; i<G[v].size(); ++i) {
            edge e = G[v][i];
            if (d[e.to] > d[v] + e.cost) {
                d[e.to] = d[v] + e.cost;
                que.push(P(d[e.to], e.to));
            }
        }
    }
}



int main(){
  int E,r;
  cin >> V >> E;
  REP(i,E){
    int f,t,c;
    cin >> f >> t >> c;
    f--;
    t--;
    edge e = {t,c};
    G[f].pb(e);
    e = {f,c}
    G[t].pb(e);
  }
  ll path[V][V];
  
  REP(i,V){

    dijkstra(i);
    REP(j,V){
      path[i][j] = d[j];
    }
  }
  
  ll sum = 0;
  REP(i,V){
    for(int j = i+1;j < V;j++){
      REP(k,G[j].size()){
	ll p = path[i][j]+G[j][k].cost;
	if(path[i][G[j][k].to] != p)
	  sum++;
      }
    }
  }
  cout << sum << endl;
  return 0;
}
