#include <bits/stdc++.h>
using namespace std;
template <class T>
inline bool chmin(T& a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T>
inline bool chmax(T& a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
struct edge {
  long long to, cost;
};
vector<vector<edge>> graph;
const long long INF = 10000000;
vector<long long> dist;
vector<long long> prever;
void dijkstra(long long n, long long s) {
  dist = vector<long long>(n, INF);
  prever = vector<long long>(n, -1);
  dist[s] = 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, s));
  while (!que.empty()) {
    pair<long long, long long> p = que.top();
    que.pop();
    long long v = p.second;
    if (dist[v] < p.first) {
      continue;
    }
    for (long long i = 0; i < graph[v].size(); i++) {
      edge e = graph[v][i];
      if (dist[e.to] > dist[v] + e.cost) {
        dist[e.to] = dist[v] + e.cost;
        prever[e.to] = v;
        que.push(pair<long long, long long>(dist[e.to], e.to));
      }
    }
  }
}
vector<long long> get_path(long long t) {
  vector<long long> path;
  for (; t != -1; t = prever[t]) {
    path.push_back(t);
  }
  reverse(path.begin(), path.end());
  return path;
}
int main() {
  long long n, m;
  cin >> n >> m;
  vector<vector<bool>> edges(n, vector<bool>(n, false));
  vector<vector<bool>> shortest(n, vector<bool>(n, false));
  vector<long long> a(m), b(m), c(m);
  for (int i = 0; i < (m); i++) {
    long long from, to, cost;
    cin >> from >> to >> cost;
    from--;
    to--;
    cost--;
    a[i] = from;
    b[i] = to;
    c[i] = cost;
    edges[from][to] = true;
    edges[to][from] = true;
  }
  for (int i = 0; i < (n); i++) {
    graph = vector<vector<edge>>(n);
    for (int j = 0; j < (m); j++) {
      graph[a[j]].push_back((edge){b[j], c[j]});
      graph[b[j]].push_back((edge){a[j], c[j]});
    }
    dijkstra(n, i);
    for (int j = 0; j < (n); j++) {
      if (i >= j) continue;
      vector<long long> path = get_path(j);
      for (int k = 0; k < (path.size() - 1); k++) {
        shortest[path[k]][path[k + 1]] = true;
        shortest[path[k + 1]][path[k]] = true;
      }
    }
  }
  long long res = 0;
  for (int i = 0; i < (n); i++) {
    for (int j = 0; j < (n); j++) {
      if (edges[i][j] && !shortest[i][j]) res++;
    }
  }
  cout << res / 2 << endl;
  return 0;
}
