#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7;
const int INF = 1e9;
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 n, m;
int main(void) {
  cin >> n >> m;
  for (int i = 0; i < (m); i++) {
    int a, b, c;
    cin >> a >> b >> c;
    a--;
    b--;
    G[a].push_back(make_pair(b, c));
    G[b].push_back(make_pair(a, c));
  }
  set<pair<int, int> > second;
  for (int i = 0; i < (n); i++)
    for (int j = 0; j < (n); j++) {
      auto ret = dijkstra(i, j);
      for (int i = 0; i < (ret.size() - 1); i++) {
        second.insert(
            make_pair(min(ret[i], ret[i + 1]), max(ret[i], ret[i + 1])));
      }
    }
  printf("%d\n", m - second.size());
}
