#include <bits/stdc++.h>
using namespace std;
struct edge {
  long long int x, c, id;
};
long long int mod(long long int a, long long int mod) {
  long long int res = a % mod;
  if (res < 0) res = res + mod;
  return res;
}
long long int modpow(long long int a, long long int n, long long int mod) {
  long long int res = 1;
  while (n > 0) {
    if (n & 1) res = res * a % mod;
    a = a * a % mod;
    n >>= 1;
  }
  return res;
}
long long int modinv(long long int a, long long int mod) {
  return modpow(a, mod - 2, mod);
}
long long int gcd(long long int a, long long int b) {
  long long int r = a % b;
  if (r == 0)
    return b;
  else
    return gcd(b, a % b);
}
bool is_prime(long long int n) {
  long long int i = 2;
  if (n == 1) return false;
  if (n == 2) return true;
  bool res = true;
  while (i * i < n) {
    if (n % i == 0) {
      res = false;
    }
    i = i + 1;
  }
  if (n % i == 0) res = false;
  return res;
}
struct dijkstra {
  long long int N;
  vector<long long int> d;
  vector<vector<edge>> e;
  dijkstra(long long int n) {
    N = n;
    e = vector<vector<edge>>(N);
  }
  void add_edge(long long int from, long long int to, long long int cost,
                long long int id) {
    e[from].push_back({to, cost, id});
  }
  void run(long long int start, long long int ign) {
    priority_queue<pair<long long int, long long int>,
                   vector<pair<long long int, long long int>>,
                   greater<pair<long long int, long long int>>>
        que;
    que.push({0, start});
    d = vector<long long int>(N, 1e18);
    d[start] = 0;
    while (!que.empty()) {
      pair<long long int, long long int> q = que.top();
      que.pop();
      long long int dc = q.first;
      long long int x = q.second;
      if (dc > d[x]) {
        continue;
      } else {
        for (auto ip : e[x]) {
          if (ip.id == ign) continue;
          if (d[ip.x] <= d[x] + ip.c) {
            continue;
          } else {
            d[ip.x] = d[x] + ip.c;
            que.push({d[ip.x], ip.x});
          }
        }
      }
    }
  }
};
int main() {
  long long int N, M;
  cin >> N >> M;
  dijkstra dijk(N);
  for (long long int i = 0; i < (M); i++) {
    long long int a, b, c;
    cin >> a >> b >> c;
    a--;
    b--;
    dijk.add_edge(a, b, c, i);
    dijk.add_edge(b, a, c, i);
  }
  vector<vector<long long int>> shortest(N, vector<long long int>(N, 1e10));
  for (long long int i = 0; i < (N - 1); i++) {
    dijk.run(i, -1);
    for (long long int j = i + 1; j < N; j++) {
      shortest[i][j] = dijk.d[j];
      cerr << shortest[i][j] << " ";
    }
    cerr << endl;
  }
  long long int ans = 0;
  for (long long int k = 0; k < (M); k++) {
    bool flg = false;
    for (long long int i = 0; i < (N - 1); i++) {
      dijk.run(i, k);
      for (long long int j = i + 1; j < N; j++) {
        if (dijk.d[j] != shortest[i][j]) {
          ans++;
          flg = true;
          break;
        }
      }
      if (flg) {
        break;
      }
    }
  }
  cout << M - ans << endl;
  return 0;
}
