#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
using vl = vector<ll>;
using vll = vector<vl>;
using vpll = vector<pll>;
void debug_out() { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(Head h, Tail... t) {
  cerr << " " << h;
  if (sizeof...(t) > 0) cerr << " :";
  debug_out(t...);
}
template <typename T>
ostream& operator<<(ostream& os, vector<T> vec) {
  for (size_t i = 0; i < vec.size(); i++)
    os << vec[i] << (i + 1 == vec.size() ? "" : " ");
  return os;
}
ll ctoi(char c) {
  switch (c) {
    case '0':
      return 0;
    case '1':
      return 1;
    case '2':
      return 2;
    case '3':
      return 3;
    case '4':
      return 4;
    case '5':
      return 5;
    case '6':
      return 6;
    case '7':
      return 7;
    case '8':
      return 8;
    case '9':
      return 9;
    default:
      return 0;
  }
}
bool pairCompare(const pll firstElof, pll secondElof) {
  return firstElof.first > secondElof.first;
}
ll i, j, k, l;
ll N, M, K, H, W, L, X, Y, Z;
ll MOD = 1000000007;
ll INF = 1LL << 60;
ll ans = 0;
ll z = 0, o = 1;
vl flag, color, D;
vector<vector<tuple<ll, ll, ll>>> path;
ll goal = 0;
void dijkstra(ll s) {
  priority_queue<pll> PQ;
  vl D(N), color(N);
  for (i = 0; i < N; i++) {
    D[i] = INF;
    color[i] = 0;
  }
  D[s] = 0;
  PQ.push(make_pair(0, s));
  color[0] = 1;
  ll q = -1;
  while (!PQ.empty()) {
    pll f = PQ.top();
    PQ.pop();
    ll u = f.second;
    color[u] = 2;
    if (D[u] < f.first * q) {
      continue;
    }
    for (j = 0; j < path[u].size(); j++) {
      ll v = get<0>(path[u][j]);
      if (color[v] == 2) {
        continue;
      }
      if (D[v] > D[u] + get<1>(path[u][j])) {
        D[v] = D[u] + get<1>(path[u][j]);
        flag[get<2>(path[u][j])] = 1;
        color[v] = 1;
        PQ.push(make_pair(D[v] * q, v));
      }
    }
  }
}
int main() {
  cin >> N >> M;
  path.resize(N);
  flag.resize(M);
  for (i = 0; i < M; i++) {
    ll a, b, c;
    cin >> a >> b >> c;
    a--;
    b--;
    path[a].push_back(make_tuple(b, c, i));
    path[b].push_back(make_tuple(a, c, i));
  }
  for (i = 0; i < N; i++) {
    dijkstra(i);
  }
  for (i = 0; i < M; i++) {
    if (flag[i] == 0) ans++;
  }
  cout << ans;
}
