#include <bits/stdc++.h>
using namespace std;
struct edge {
  int to, cost;
};
int n, inf = 1000000007;
vector<edge> g[110];
int d[110];
int pre[110];
map<pair<int, int>, bool> mp;
int kekka = 0;
void dijkstra(int s) {
  for (int i = 1; i <= n; i++) {
    d[i] = inf;
  }
  for (int i = 0; i <= n; i++) {
    pre[i] = -1;
  }
  priority_queue<pair<int, int>, vector<pair<int, int>>,
                 greater<pair<int, int>>>
      que;
  d[1] = 0;
  que.push(pair<int, int>(0, s));
  while (!que.empty()) {
    pair<int, int> 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;
        pre[e.to] = v;
        que.push(pair<int, int>(d[e.to], e.to));
      }
    }
  }
}
void get_path(int t) {
  for (; pre[t] != -1; t = pre[t]) {
    if (mp[pair<int, int>(t, pre[t])] != true &&
        mp[pair<int, int>(pre[t], t)] != true) {
      kekka++;
      mp[pair<int, int>(t, pre[t])] = true;
      mp[pair<int, int>(pre[t], t)] = true;
    }
  }
}
int main() {
  int m;
  cin >> n >> m;
  for (int i = 0; i < m; i++) {
    edge e;
    int a;
    cin >> a >> e.to >> e.cost;
    g[a].push_back(e);
    g[e.to].push_back(e);
    mp[pair<int, int>(a, e.to)] = false;
    mp[pair<int, int>(e.to, a)] = false;
  }
  for (int i = 1; i <= n; i++) {
    dijkstra(i);
    for (int j = 1; j <= n; j++) {
      if (i == j) continue;
      get_path(j);
    }
  }
  cout << m - kekka << endl;
}
