#include <bits/stdc++.h>
using namespace std;
const long long LINF = 1001002003004005006ll;
int dx[] = {1, 0, -1, 0};
int dy[] = {0, 1, 0, -1};
long long gcd(long long a, long long b) { return b ? gcd(b, a % b) : a; }
template <class T>
bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T>
bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return 1;
  }
  return 0;
}
struct edge {
  long long to, cost;
};
struct graph {
  long long V;
  vector<vector<edge>> G;
  vector<long long> d;
  vector<long long> path;
  vector<long long> prev;
  graph(long long n) { init(n); }
  void init(long long n) {
    V = n;
    G.resize(V);
    d.resize(V);
    prev.resize(V);
    for (int i = 0; i < V; i++) {
      d[i] = LINF;
      prev[i] = -1;
    }
  }
  void add_edge(long long s, long long t, long long cost) {
    edge e;
    e.to = t, e.cost = cost;
    G[s].push_back(e);
  }
  void dijkstra(long long s) {
    for (int i = 0; i < V; i++) {
      d[i] = 1000000000;
    }
    d[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 (d[v] < p.first) continue;
      for (auto e : G[v]) {
        if (d[e.to] > d[v] + e.cost) {
          d[e.to] = d[v] + e.cost;
          prev[e.to] = v;
          que.push(pair<long long, long long>(d[e.to], e.to));
        }
      }
    }
  }
  vector<int> get_path(long long g) {
    vector<int> ret;
    for (; g != -1; g = prev[g]) {
      ret.push_back(g);
    }
    reverse(ret.begin(), ret.end());
    return ret;
  }
};
int main() {
  int n, m;
  cin >> n >> m;
  graph G(n);
  vector<pair<int, int>> ed;
  for (int i = 0; i < m; i++) {
    int a, b, c;
    cin >> a >> b >> c;
    a--, b--;
    G.add_edge(a, b, c);
    G.add_edge(b, a, c);
    ed.push_back(make_pair(min(a, b), max(a, b)));
  }
  int ans = 0;
  for (auto x : ed) {
    int u = x.first, v = x.second;
    G.dijkstra(u);
    auto tmp = G.get_path(v);
    if (tmp.size() != 1) ans++;
  }
  cout << ans << endl;
  return 0;
}
