#include <bits/stdc++.h>
using namespace std;
long long MOD = 1000000007;
long long powM(long long base, long long exp) {
  long long ret = 1;
  long long buf = base;
  while (exp > 0) {
    if (exp & 1) {
      ret *= buf;
    }
    buf = buf * buf % MOD;
    exp >>= 1;
  }
  return ret;
}
long long combM(long long a, long long b) {
  if (b == 0) {
    return 1;
  }
  if (a - b < b) {
    return combM(a, a - b);
  }
  long long ans = 1;
  for (long long i = 1; i < b + 1; i++) {
    ans *= a + 1 - i;
    ans /= i;
  }
  return ans;
}
void solve();
signed main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  solve();
  return 0;
}
struct Task {
  long long place, cost;
  vector<pair<long long, long long>> paths;
  bool operator<(const Task& another) const { return cost < another.cost; }
  bool operator>(const Task& another) const { return cost > another.cost; }
};
long long paths[100][100];
vector<long long> adjs[100];
bool passed[100][100];
void solve() {
  long long N;
  cin >> N;
  long long M;
  cin >> M;
  for (long long i = 0; i < M; i++) {
    long long a, b, c;
    cin >> a >> b >> c;
    a--;
    b--;
    paths[a][b] = c;
    adjs[a].emplace_back(b);
    adjs[b].emplace_back(a);
  }
  long long cnt = 0;
  for (long long i = 0; i < N; i++) {
    for (long long j = i + 1; j < N; j++) {
      if (passed[i][j]) {
        continue;
      }
      priority_queue<Task, vector<Task>, greater<Task>> q;
      bool saw[100] = {};
      saw[i] = true;
      q.push(Task{i, 0});
      while (!q.empty()) {
        Task last = q.top();
        saw[last.place] = true;
        for (pair<long long, long long> path : last.paths) {
          long long n = min(path.first, path.second);
          long long x = max(path.first, path.second);
          if (!passed[n][x]) {
            passed[n][x] = true;
            cnt++;
          }
        }
        q.pop();
        if (last.place == j) {
          break;
        }
        for (long long next : adjs[last.place]) {
          if (saw[next]) {
            continue;
          }
          vector<pair<long long, long long>> newv;
          long long n = min(last.place, next);
          long long x = max(last.place, next);
          if (!passed[n][x]) {
            pair<long long, long long> ins = make_pair(n, x);
            newv.emplace_back(ins);
          }
          q.push(Task{next, last.cost + paths[n][x], newv});
        }
      }
    }
  }
  cout << M - cnt << endl;
  ;
}
