#include <bits/stdc++.h>
using namespace std;
template <class T, class U>
void cmax(T& a, U b) {
  if (a < b) a = b;
}
template <class T, class U>
void cmin(T& a, U b) {
  if (a > b) a = b;
}
int n;
const int INF = 1e9;
set<pair<int, int>> used;
using T = tuple<int, int, int>;
bool compt(T l, T r) { return get<2>(l) < get<2>(r); }
vector<int> dijkstra(int s, vector<vector<pair<int, int>>> G) {
  priority_queue<T, vector<T>, greater<T>> que;
  vector<int> d(n, INF);
  d[s] = 0;
  que.push(T(0, s, 0));
  while (!que.empty()) {
    T p = que.top();
    que.pop();
    int v = get<0>(p);
    int dis = get<1>(p);
    int pre = get<2>(p);
    if (d[v] < dis) continue;
    if (v != pre) used.insert(pair<int, int>(min(v, pre), max(v, pre)));
    for (auto&& e : G[v]) {
      if (d[e.first] > d[v] + e.second) {
        d[e.first] = d[v] + e.second;
        que.push(T(e.first, d[e.first], v));
      }
    }
  }
  return d;
}
int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  int m;
  cin >> n >> m;
  vector<vector<pair<int, int>>> graph(n);
  for (long long i = 0; i < m; i++) {
    int a, b, c;
    cin >> a >> b >> c;
    a--;
    b--;
    graph[a].push_back(pair<int, int>(b, c));
    graph[b].push_back(pair<int, int>(a, c));
  }
  vector<vector<int>> ans(n);
  for (long long i = 0; i < n; i++) {
    ans[i] = dijkstra(i, graph);
  }
  cout << m - used.size() << endl;
}
