#include <bits/stdc++.h>
const int INF = 1e9 + 7;
using namespace std;
struct edge {
  int to, cost;
};
struct inp {
  int a, b, c;
};
int V;
vector<edge> G[100];
int d[100];
void dijkstra(int s) {
  priority_queue<pair<int, int>, vector<pair<int, int>>,
                 greater<pair<int, int>>>
      que;
  fill(d, d + V, INF);
  d[s] = 0;
  que.push(pair<int, int>(0, s));
  while (!que.empty()) {
    pair<int, int> p = que.top();
    que.pop();
    int v = p.second;
    if (d[v] < p.first) continue;
    for (int i = (0); i < (G[v].size()); ++i) {
      edge e = G[v][i];
      if (d[e.to] > d[v] + e.cost) {
        d[e.to] = d[v] + e.cost;
        que.push(pair<int, int>(d[e.to], e.to));
      }
    }
  }
}
int main() {
  int e;
  bool used[100];
  scanf("%d%d", &V, &e);
  vector<inp> iedge(e);
  for (int i = (0); i < (e); ++i) {
    int a, b, c;
    scanf("%d%d%d", &a, &b, &c);
    --a;
    --b;
    edge e1 = {b, c}, e2 = {a, c};
    G[a].push_back(e1);
    G[b].push_back(e2);
    inp e3 = {a, b, c};
    iedge[i] = e3;
  }
  for (int i = (0); i < (e); ++i) used[i] = false;
  for (int i = (0); i < (V); ++i) {
    dijkstra(i);
    for (int j = (0); j < (e); ++j) {
      if (used[j]) continue;
      if (d[iedge[j].a] + iedge[j].c == d[iedge[j].b]) used[j] = true;
    }
  }
  int ans = 0;
  for (int i = (0); i < (e); ++i)
    if (!used[i]) ++ans;
  printf("%d\n", ans);
  return 0;
}
