#include <bits/stdc++.h>
using namespace std;
template <typename A, size_t N, typename T>
void Fill(A (&array)[N], const T &val) {
  std::fill((T *)array, (T *)(array + N), val);
}
struct edge {
  long long to;
  long long cost;
  long long id;
};
vector<edge> G[100010];
int main() {
  long long n, m;
  std::cin >> n >> m;
  long long id = 0;
  for (int i = 0; i < m; i++) {
    long long tmpa, tmpb, tmpc;
    std::cin >> tmpa >> tmpb >> tmpc;
    tmpa--;
    tmpb--;
    G[tmpa].push_back({tmpb, tmpc, id});
    G[tmpb].push_back({tmpa, tmpc, id});
    id++;
  }
  long long d[101][101];
  Fill(d, 1e10);
  bool use[1010];
  Fill(use, false);
  for (int i = 0; i < n; i++) {
    long long ans[101];
    Fill(ans, 0);
    for (int k = -1; k < m; k++) {
      Fill(d, 1e10);
      d[i][i] = 0;
      priority_queue<pair<long long, long long>,
                     vector<pair<long long, long long> >,
                     greater<pair<long long, long long> > >
          que;
      que.push(pair<long long, long long>(0, i));
      while (!que.empty()) {
        pair<long long, long long> p = que.top();
        que.pop();
        long long v = p.second;
        if (d[i][v] < p.first) continue;
        for (int i = 0; i < G[v].size(); ++i) {
          edge e = G[v][i];
          if (e.id == k) continue;
          if (d[i][e.to] > d[i][v] + e.cost) {
            d[i][e.to] = d[i][v] + e.cost;
            que.push(pair<long long, long long>(d[i][e.to], e.to));
          }
        }
      }
      for (int j = i + 1; j < n; j++) {
        if (k == -1) {
          ans[j] = d[i][j];
        } else {
          if (ans[j] != d[i][j]) use[k] = true;
        }
      }
    }
  }
  long long result = 0;
  for (int i = 0; i < m; i++) {
    if (!use[i]) result++;
  }
  std::cout << result << std::endl;
}
