#include <bits/stdc++.h>
struct edge {
  int to;
  int cost;
};
int n, m;
std::vector<edge> edges[100];
std::set<std::pair<int, int>> path;
void dijkstra(int s) {
  int prev[100];
  std::fill(prev, prev + n, -1);
  int dist[100];
  std::fill(dist, dist + n, 1e9);
  dist[s] = 0;
  using pair = std::pair<int, int>;
  std::priority_queue<pair, std::vector<pair>, std::greater<pair>> q;
  q.emplace(pair{0, s});
  while (!q.empty()) {
    auto p = q.top();
    q.pop();
    int v = p.second;
    if (dist[v] < p.first) continue;
    for (auto e : edges[v]) {
      if (dist[e.to] > dist[v] + e.cost) {
        dist[e.to] = dist[v] + e.cost;
        q.emplace(pair{dist[e.to], e.to});
        prev[e.to] = v;
      }
    }
  }
  for (int t = s + 1; t != -1 && t != n; t = prev[t]) {
    if (prev[t] == -1) break;
    path.insert(pair{std::min(t, prev[t]), std::max(t, prev[t])});
  }
}
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 0; i < m; ++i) {
    int a, b, c;
    scanf("%d%d%d", &a, &b, &c);
    --a, --b;
    edges[a].emplace_back(edge{b, c});
    edges[b].emplace_back(edge{a, c});
  }
  for (int i = 0; i < n; ++i) {
    dijkstra(i);
  }
  printf("%d\n", m - path.size());
  return 0;
}
