#include <bits/stdc++.h>
using namespace std;
void regenerate_path(int start, int end, vector<vector<pair<int, int>>> dp,
                     set<pair<int, int>> &paths) {
  vector<pair<int, int>> path;
  if (dp[start][end].second == start) {
    paths.insert({min(start, end), max(start, end)});
    return;
  }
  regenerate_path(start, dp[start][end].second, dp, paths);
  regenerate_path(dp[start][end].second, end, dp, paths);
  return;
};
int main() {
  int n, m;
  cin >> n >> m;
  struct edge {
    int a, b, c;
  };
  vector<edge> edges(m);
  for (int i = 0; i < m; i++) {
    int a, b, c;
    cin >> a >> b >> c;
    edges[i] = {a - 1, b - 1, c};
  }
  const int max_dist = 1000 * 1000 + 1;
  vector<vector<pair<int, int>>> dp(n,
                                    vector<pair<int, int>>(n, {max_dist, -1}));
  for (auto e : edges) {
    dp[e.a][e.b] = {e.c, e.a};
    dp[e.b][e.a] = {e.c, e.b};
  }
  for (int i = 0; i < n; i++) {
    dp[i][i] = {0, -1};
  }
  for (int k = 0; k < n; k++) {
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        if (dp[i][j].first > dp[i][k].first + dp[k][j].first) {
          dp[i][j].first = dp[i][k].first + dp[k][j].first;
          dp[i][j].second = k;
        }
      }
    }
  }
  set<pair<int, int>> paths;
  for (int i = 0; i < n - 1; i++) {
    for (int j = i + 1; j < n; j++) {
      regenerate_path(i, j, dp, paths);
    }
  }
  cout << m - paths.size() << endl;
  return 0;
}
