#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
void ins() {}
template <class T, class... Rest>
void ins(T& v, Rest&... rest) {
  cin >> v;
  ins(rest...);
}
struct Graph {
  vector<map<int, long long>> edge;
  Graph(int n = 0) { resize(n); }
  void resize(int n) { edge.resize(n, map<int, long long>()); }
  void addEdge(int from, int to, long long weight, bool directed = false) {
    edge[from][to] = weight;
    if (!directed) edge[to][from] = weight;
  }
  map<int, long long>& operator[](int from) { return edge[from]; }
};
template <class T>
using vv = vector<vector<T>>;
const ll INF = 1e15;
int main() {
  int N;
  cin >> N;
  ;
  int M;
  cin >> M;
  ;
  Graph G(N);
  vv<ll> cost(N, vector<ll>(N, INF));
  vi A(N), B(N), C(N);
  for (int i = 0, _i = (M); i < _i; ++i) {
    ins(A[i], B[i], C[i]);
    --A[i], --B[i];
    cost[A[i]][B[i]] = cost[B[i]][A[i]] = C[i];
    G.addEdge(A[i], B[i], C[i]);
  }
  for (int i = 0, _i = (N); i < _i; ++i) cost[i][i] = 0;
  for (int k = 0, _i = (N); k < _i; ++k)
    for (int i = 0, _i = (N); i < _i; ++i)
      for (int j = 0, _i = (N); j < _i; ++j)
        cost[i][j] = min(cost[i][j], cost[i][k] + cost[k][j]);
  int ans = 0;
  for (int i = 0, _i = (M); i < _i; ++i) {
    bool ok = false;
    for (int from = 0, _i = (N); from < _i; ++from)
      for (int to = 0, _i = (N); to < _i; ++to) {
        if (cost[from][to] == cost[from][A[i]] + C[i] + cost[B[i]][to]) {
          ok = true;
          break;
        }
      }
    if (!ok) ++ans;
  }
  cout << ans << endl;
  return 0;
}
