#include <bits/stdc++.h>
bool debug = true;
const long long WEIGHT_INF = std::numeric_limits<long long>::max() / 4;
struct Edge {
  int src, dst;
  long long weight;
};
bool operator<(const Edge& a, const Edge& b) { return (a.weight < b.weight); };
bool operator>(const Edge& a, const Edge& b) { return (a.weight > b.weight); };
std::vector<std::vector<long long> > g, ord;
;
std::vector<std::vector<int> > trace;
void warshallFloyd() {
  int n = g.size();
  trace.resize(n, std::vector<int>(n, -1));
  for (long k = 0; k < (n); ++k)
    for (long i = 0; i < (n); ++i)
      for (long j = 0; j < (n); ++j) {
        if (g[i][k] == -1 || g[k][j] == -1) {
          continue;
        }
        g[i][j] = std::min(g[i][j], g[i][k] + g[k][j]);
      }
}
int N, M;
int main() {
  std::cin >> N >> M;
  ord.resize(N, std::vector<long long>(N, -1));
  g.resize(N, std::vector<long long>(N, -1));
  for (long i = 0; i < (M); ++i) {
    int a, b, c;
    std::cin >> a >> b >> c;
    a--, b--;
    ord[a][b] = c;
    ord[b][a] = c;
    g[a][b] = c;
    g[b][a] = c;
  }
  warshallFloyd();
  long ans = 0;
  for (long i = 0; i < (N); ++i) {
    for (int j = i + 1; j < N; ++j) {
      ans += (int)(g[i][j] < ord[i][j]);
    }
  }
  std::cout << ans << std::endl;
}
