#include <bits/stdc++.h>
using namespace std;
template <class T>
bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
}
template <class T>
bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return 1;
  }
}
struct Edge {
  long long to;
  long long weight;
  Edge(long long t, long long w) : to(t), weight(w) {}
};
using Graph = vector<vector<Edge>>;
using P = pair<long long, long long>;
const int INF = 100000000;
vector<vector<int>> d;
void warshall_floyd(int n) {
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++)
      for (int k = 0; k < n; k++) d[j][k] = min(d[j][k], d[j][i] + d[i][k]);
}
int main() {
  int n, m;
  cin >> n >> m;
  Graph G(n);
  vector<vector<int>> keiro(n, vector<int>(n, -1));
  d = vector<vector<int>>(n, vector<int>(n, INF));
  for (int i = 0; i < n; i++) d[i][i] = 0;
  for (long long i = 0; i < (long long)(m); ++i) {
    int a, b, c;
    cin >> a >> b >> c;
    a--;
    b--;
    G[a].emplace_back(b, c);
    G[b].emplace_back(a, c);
    d[a][b] = c;
    d[b][a] = c;
    keiro[a][b] = i;
    keiro[b][a] = i;
  }
  warshall_floyd(n);
  queue<int> que;
  que.push(0);
  vector<bool> use(m, false);
  vector<bool> seen(n, false);
  seen[0] = true;
  while (!que.empty()) {
    int v = que.front();
    que.pop();
    for (Edge e : G[v]) {
      int u = e.to;
      if (!seen[u]) {
        seen[u] = true;
        if (d[v][u] == e.weight) use[keiro[v][u]] = true;
        que.push(u);
      }
    }
  }
  int ans = 0;
  for (long long i = 0; i < (long long)(m); ++i)
    if (!use[i]) ans++;
  cout << ans << endl;
  return 0;
}
