#include <bits/stdc++.h>
using namespace std;
struct node {
  int xx;
  int brojac;
};
vector<vector<pair<int, pair<int, int> > > > v;
bool const operator<(const node& x, const node& y) {
  if (x.brojac != y.brojac)
    return x.brojac > y.brojac;
  else
    return x.xx > y.xx;
}
vector<int> dist(101, 1e9);
vector<pair<int, int> > pat(101, make_pair(-2, -1));
int main() {
  int n, m;
  cin >> n >> m;
  vector<pair<int, pair<int, int> > > vec;
  v.insert(v.begin(), n + 1, vec);
  for (int i = 0; i < m; i++) {
    int a, b, c;
    cin >> a >> b >> c;
    a--;
    b--;
    v[a].push_back(make_pair(b, make_pair(c, i)));
    v[b].push_back(make_pair(a, make_pair(c, i)));
  }
  vector<bool> visited(m + 1, 0);
  priority_queue<node> qi;
  node g;
  g.xx = 0;
  g.brojac = 0;
  dist[0] = 0;
  pat[0] = make_pair(-1, -1);
  qi.push(g);
  while (!qi.empty()) {
    int topi = qi.top().xx;
    int tops = qi.top().brojac;
    qi.pop();
    for (int i = 0; i < v[topi].size(); i++) {
      if (tops + v[topi][i].second.first < dist[v[topi][i].first]) {
        pat[v[topi][i].first] = make_pair(topi, v[topi][i].second.second);
        dist[v[topi][i].first] = tops + v[topi][i].second.first;
        g.xx = v[topi][i].first;
        g.brojac = tops + v[topi][i].second.first;
        qi.push(g);
      }
    }
  }
  for (int i = 1; i < n; i++) {
    int y = i;
    while (y != -1) {
      if (pat[y].second != -1) visited[pat[y].second] = true;
      y = pat[y].first;
    }
  }
  int brojac1 = 0;
  for (int i = 0; i < m; i++) {
    if (!visited[i]) brojac1++;
  }
  cout << brojac1 << endl;
  return 0;
}
