#include <bits/stdc++.h>
using namespace std;
const int inf = 1e7;
struct dat {
  int at, cost, from;
  dat() { at = cost = from = -1; }
  dat(int a, int b, int c) : at(a), cost(b), from(c) {}
};
signed main() {
  int n, m;
  cin >> n >> m;
  vector<vector<int>> G(n, vector<int>(n, inf));
  vector<vector<bool>> H(n, vector<bool>(n, false));
  for (int i = 0; i < m; ++i) {
    int a, b, c;
    cin >> a >> b >> c;
    --a;
    --b;
    G[a][b] = G[b][a] = c;
  }
  auto f = [](dat a, dat b) { return a.cost > b.cost; };
  for (int src = 0; src < n; ++src) {
    priority_queue<dat, vector<dat>, decltype(f)> que(f);
    vector<bool> vis(n, false);
    vector<int> frm(n, -1);
    vector<int> trm;
    que.push(dat(src, 0, -1));
    for (int vsn = 0; vsn < n; ++vsn) {
      dat q = que.top();
      que.pop();
      vis[q.at] = true;
      if (q.from != -1) frm[q.at] = q.from;
      bool istrm = true;
      for (int i = 0; i < n; ++i) {
        if (vis[i]) continue;
        if (G[q.at][i] < inf)
          que.push(dat(i, G[q.at][i] + q.cost, q.at)), istrm = false;
      }
      if (istrm) trm.push_back(q.at);
    }
    bool sm = false;
    while (!sm) {
      sm = true;
      for (int i = 0; i < trm.size(); ++i) {
        if (frm[trm[i]] == trm[i] || frm[trm[i]] < 0) continue;
        sm = false;
        int p = trm[i], q = frm[p];
        H[p][q] = H[q][p] = true;
        trm[i] = q;
      }
    }
  }
  int r = 0;
  for (int i = 0; i < n - 1; ++i) {
    for (int j = i + 1; j < n; ++j) {
      if (H[i][j]) ++r;
    }
  }
  cout << m - r;
}
