#include <bits/stdc++.h>
using namespace std;
struct hoge {
  long long from, to, cost;
  bool bo;
  bool operator>(const hoge& huga) const { return cost > huga.cost; }
};
void dijkstra(long long I);
long long n, m, a, b, c, ans, memo[100][100];
vector<hoge> v[100];
signed main() {
  cin >> n >> m;
  for (long long i = 0; i < (long long)(m); ++i) {
    cin >> a >> b >> c;
    a--, b--;
    hoge tmp{a, b, c};
    v[a].push_back(tmp);
    swap(tmp.from, tmp.to);
    v[b].push_back(tmp);
  }
  for (long long i = 0; i < (long long)(n); ++i) dijkstra(i);
  for (long long i = 0; i < (long long)(n); ++i)
    for (long long j = 0; j < (long long)(v[i].size()); ++j)
      if (!memo[v[i][j].from][v[i][j].to]) ans++;
  cout << ans / 2 << endl;
}
void dijkstra(long long I) {
  long long visited[100] = {};
  priority_queue<hoge, vector<hoge>, greater<hoge>> pq;
  for (long long i = 0; i < (long long)(v[I].size()); ++i) pq.push(v[I][i]);
  while (!pq.empty()) {
    long long from = pq.top().from, to = pq.top().to, cost = pq.top().cost;
    pq.pop();
    if (visited[to]) {
      if (visited[to] == visited[from] + cost)
        memo[from][to] = true, memo[to][from] = true;
      continue;
    }
    visited[to] = visited[from] + cost;
    memo[from][to] = true;
    memo[to][from] = true;
    for (long long i = 0; i < (long long)(v[to].size()); ++i) pq.push(v[to][i]);
  }
}
