#include <bits/stdc++.h>
using namespace std;
void printbit(int u) {
  if (u == 0)
    cout << 0;
  else {
    int s = 0, k = 0;
    for (; 0 < u; u >>= 1, k++) s = (s << 1) | (u & 1);
    for (; 0 < k--; s >>= 1) cout << (s & 1);
  }
}
template <typename T1, typename T2>
ostream& operator<<(ostream& o, const pair<T1, T2> p) {
  o << "(" << p.first << ":" << p.second << ")";
  return o;
}
class Flow {
 public:
  size_t n;
  struct Arrow {
    int from, to;
    int w_max;
    Arrow(int from = 0, int to = 0, int w = 1) : from(from), to(to), w_max(w) {}
  };
  vector<vector<int>> vertex_to;
  vector<vector<int>> vertex_from;
  vector<Arrow> arrow;
  Flow(int n, int m = 5010) : n(n), vertex_to(n), vertex_from(n) {
    arrow.reserve(m);
  }
  void connect(int from, int to, int w_max) {
    vertex_to[from].push_back(arrow.size());
    vertex_from[to].push_back(arrow.size());
    arrow.emplace_back(from, to, w_max);
  }
  size_t degree(int v) { return vertex_to[v].size() + vertex_from[v].size(); }
  size_t degree_in(int v) { return vertex_from[v].size(); }
  size_t degree_out(int v) { return vertex_to[v].size(); }
};
int width, height;
int m, n;
int main() {
  int i, j, k;
  int x, y, a, b;
  cin >> n >> m;
  Flow graph(n, m + 10);
  set<pair<int, int>> check;
  for (i = 0; i < m; i++) {
    scanf("%d%d%d", &a, &b, &x);
    a--;
    b--;
    graph.connect(a, b, x);
  }
  vector<bool> visited(n);
  for (int start = 0; start < n; start++) {
    fill((visited).begin(), (visited).end(), false);
    priority_queue<vector<int>> pq;
    pq.emplace(vector<int>{0, start, start});
    while (!pq.empty()) {
      const vector<int>& p = pq.top();
      int dist = -p[0];
      int v = p[1];
      int u = p[2];
      pq.pop();
      if (visited[v]) {
        continue;
      }
      visited[v] = true;
      if (u != v) {
        if (u < v)
          check.insert(make_pair(u, v));
        else
          check.insert(make_pair(v, u));
      }
      for (int ia : graph.vertex_to[v]) {
        Flow::Arrow& a = graph.arrow[ia];
        if (!visited[a.to]) {
          pq.emplace(vector<int>{-(dist + a.w_max), a.to, v});
        }
      }
      for (int ia : graph.vertex_from[v]) {
        Flow::Arrow& a = graph.arrow[ia];
        if (!visited[a.from]) {
          pq.emplace(vector<int>{-(dist + a.w_max), a.from, v});
        }
      }
    }
  }
  cout << (m - (int)check.size()) << endl;
  return 0;
}
