#include <bits/stdc++.h>
using namespace std;
int dp[100][100];
bool used[100][100];
const int INF = 1145141919;
int main() {
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      dp[i][j] = INF;
    }
    dp[i][i] = 0;
  }
  vector<pair<int, int> > road[n];
  for (int i = 0; i < m; ++i) {
    int a, b, c;
    cin >> a >> b >> c;
    --a;
    --b;
    road[a].push_back(pair<int, int>(b, c));
    road[b].push_back(pair<int, int>(a, c));
    used[a][b] = used[b][a] = 1;
  };
  for (int i = 0; i < n; ++i) {
    priority_queue<tuple<int, int, pair<int, int> >,
                   vector<tuple<int, int, pair<int, int> > >,
                   greater<tuple<int, int, pair<int, int> > > >
        q;
    q.push(tuple<int, int, pair<int, int> >(i, 0, pair<int, int>(i, i)));
    while (!q.empty()) {
      auto t = q.top();
      q.pop();
      if (dp[i][get<1>(t)] < get<0>(t)) continue;
      dp[i][get<1>(t)] = get<0>(t);
      used[get<2>(t).first][get<2>(t).second] =
          used[get<2>(t).second][get<2>(t).first] = 0;
      for (pair<int, int> u : road[get<1>(t)]) {
        if (dp[i][get<1>(t)] + u.second < dp[i][u.first]) {
          q.push(tuple<int, int, pair<int, int> >(
              u.first, dp[i][get<1>(t)] + u.second,
              pair<int, int>(get<1>(t), u.first)));
        }
      }
    }
  }
  int ans = 0;
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      ans += used[i][j];
    }
  }
  cout << ans / 2 << endl;
  return 0;
}
