#include <bits/stdc++.h>
using namespace std;
const long long MOD = 1e9 + 7;
template <typename T>
struct edge {
  long long src, to;
  T cost;
  edge(long long to, T cost) : src(-1), to(to), cost(cost) {}
  edge(long long src, long long to, T cost) : src(src), to(to), cost(cost) {}
  edge& operator=(const int& x) {
    to = x;
    return *this;
  }
  operator int() const { return to; }
};
template <typename T>
using Edges = vector<edge<T>>;
template <typename T>
using WeightedGraph = vector<Edges<T>>;
using UnWeightedGraph = vector<vector<int>>;
template <typename T>
using Matrix = vector<vector<T>>;
vector<vector<bool>> check;
template <typename T>
vector<T> dijkstra(WeightedGraph<T>& g, int s) {
  const auto INF = numeric_limits<T>::max();
  vector<T> dist(g.size(), INF);
  using Pi = pair<T, int>;
  priority_queue<Pi, vector<Pi>, greater<Pi>> que;
  dist[s] = 0;
  que.emplace(dist[s], s);
  while (!que.empty()) {
    T cost;
    int idx;
    tie(cost, idx) = que.top();
    que.pop();
    if (dist[idx] < cost) continue;
    for (long long n = 0; n < g[idx].size(); n++) {
      auto e = g[idx][n];
      auto next_cost = cost + e.cost;
      if (dist[e.to] <= next_cost) continue;
      dist[e.to] = next_cost;
      check[idx][n] = true;
      que.emplace(dist[e.to], e.to);
    }
  }
  return dist;
}
long long N, M;
int main() {
  cin >> N >> M;
  WeightedGraph<long long> G(N);
  check.resize(N);
  for (long long m = 0; m < M; m++) {
    long long a, b, c;
    cin >> a >> b >> c;
    a--;
    b--;
    G[a].push_back({a, b, c});
    G[b].push_back({b, a, c});
    check[a].push_back(false);
    check[b].push_back(false);
  }
  for (long long n = 0; n < N; n++) dijkstra(G, n);
  long long ans = 0;
  for (long long s = 0; s < N; s++) {
    for (long long n = 0; n < G[s].size(); n++) {
      auto ed = G[s][n];
      long long t = ed.to;
      bool used = false;
      for (long long m = 0; m < G[t].size(); m++) {
        if (G[t][m].to == n) {
          if (check[t][m]) used = true;
          break;
        }
      }
      if (!used && !check[s][n]) ans++;
    }
  }
  cout << ans / 2 << endl;
  return 0;
}
