#include <bits/stdc++.h>
inline int rit() {
  int f = 0, key = 1;
  char ch;
  do {
    ch = getchar();
    if (ch == '-') key = -1;
    ;
  } while (ch < '0' || ch > '9');
  do {
    f = f * 10 + ch - '0';
    ch = getchar();
  } while (ch >= '0' && ch <= '9');
  return f * key;
}
using namespace std;
int mp[101][101], dis[101];
bool used[101][101], visit[101];
struct edge {
  int a, b, d;
};
bool operator<(const edge& e1, const edge& e2) { return e1.d > e2.d; }
int main(void) {
  int n, m, u, v;
  n = rit(), m = rit();
  for (int i = 0; i < int(m); i++) {
    u = rit(), v = rit(), mp[u][v] = rit();
    mp[v][u] = mp[u][v];
  }
  for (int i = 1; i <= int(n); i++) {
    memset(visit, false, sizeof(visit));
    priority_queue<edge> pq;
    pq.push((edge){i, i, 0});
    for (int j = 1; j <= int(n); j++) {
      while (!pq.empty() && visit[pq.top().b]) pq.pop();
      edge tmp = pq.top();
      pq.pop();
      if (tmp.a != tmp.b) used[tmp.a][tmp.b] = true;
      visit[tmp.b] = true;
      dis[tmp.b] = tmp.d;
      for (int k = 1; k <= int(n); k++) {
        if (visit[k]) continue;
        if (mp[tmp.b][k]) {
          pq.push((edge){tmp.b, k, dis[tmp.b] + mp[tmp.b][k]});
        }
      }
    }
  }
  int cnt = 0;
  for (int i = 1; i <= int(n); i++)
    for (int j = 1; j <= int(n); j++)
      if (used[i][j]) cnt++;
  printf("%d\n", m - cnt / 2);
}
