#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7;
const int INF = 1e9;
const long long INFF = 1e18;
const int MAX_N = 110;
vector<pair<int, int>> G[MAX_N];
vector<int> dijkstra(int start, int goal) {
  vector<long long> dist(MAX_N, INF);
  vector<int> pre(MAX_N, -1);
  dist[start] = 0;
  priority_queue<pair<int, int>, vector<pair<int, int>>,
                 greater<pair<int, int>>>
      que;
  que.push(make_pair(0, start));
  while (!que.empty()) {
    int cost, u, t;
    cost = que.top().first, u = que.top().second;
    que.pop();
    if (dist[u] < cost) continue;
    for (auto tmp : G[u]) {
      int v = tmp.first, time = tmp.second;
      if (dist[v] > dist[u] + time) {
        dist[v] = dist[u] + time;
        pre[v] = u;
        que.push(make_pair(dist[v], v));
      } else if (dist[v] == dist[u] + time) {
        pre[v] = min(pre[v], u);
      }
    }
  }
  vector<int> path;
  int s = start, t = goal;
  for (; t != s; t = pre[t]) path.push_back(t);
  path.push_back(s);
  return path;
}
int a[1010], b[1010], c[1010];
int main(void) {
  int N, M;
  cin >> N >> M;
  for (int i = 0; i < (M); i++) {
    cin >> a[i] >> b[i] >> c[i];
    a[i]--;
    b[i]--;
  }
  for (int i = 0; i < (M); i++)
    G[a[i]].push_back(make_pair(b[i], c[i])),
        G[b[i]].push_back(make_pair(a[i], c[i]));
  set<pair<int, int>> second;
  for (int s = 0; s < (N); s++)
    for (int t = 0; t < (N); t++) {
      if (s == t) continue;
      auto d = dijkstra(s, t);
      for (int i = 0; i < (d.size() - 1); i++) {
        second.insert(make_pair(min(d[i], d[i + 1]), max(d[i], d[i + 1])));
      }
    }
  printf("%d\n", M - (int)second.size());
  return 0;
}
