#include <bits/stdc++.h>
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
using namespace std;
template <class T>
inline bool chmax(T& a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T>
inline bool chmin(T& a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
const int MOD = 1e9 + 7;
const long long INF = 1e18;
const double PI = acos(-1);
int dx[8] = {1, 0, -1, 0, 1, 1, -1, -1};
int dy[8] = {0, 1, 0, -1, -1, 1, 1, -1};
const int MAX = 510000;
int dist[110][110];
int pre[110][110];
int use[110][110];
int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  int n, m;
  cin >> n >> m;
  for (long long i = 0; i < n; ++i)
    for (long long j = 0; j < n; ++j) {
      dist[i][j] = MOD;
      pre[i][j] = i;
    }
  while (m--) {
    int a, b, c;
    cin >> a >> b >> c;
    a--;
    b--;
    dist[a][b] = c;
    dist[b][a] = c;
    use[a][b]++;
    use[b][a]++;
  }
  for (long long k = 0; k < n; ++k)
    for (long long i = 0; i < n; ++i)
      for (long long j = 0; j < n; ++j) {
        chmin(dist[i][j], dist[i][k] + dist[k][j]);
        if (dist[i][j] < dist[i][k] + dist[k][j]) pre[i][j] = pre[k][j];
      }
  for (long long i = 0; i < n; ++i)
    for (long long j = 0; j < n; ++j) {
      vector<int> vec;
      for (int now = j; now != i; now = pre[i][now]) {
        vec.emplace_back(now);
      }
      vec.emplace_back(i);
      for (long long k = 0; k < vec.size() - 1; ++k) {
        use[vec[k]][vec[k + 1]]--;
      }
    }
  int ans = 0;
  for (long long i = 0; i < n; ++i)
    for (long long j = 0; j < n; ++j)
      if (use[i][j] > 0) ans++;
  cout << ans / 2 << '\n';
  return 0;
}
