#include <bits/stdc++.h>
using namespace std;
const int INF = 1 << 29;
int N, M;
vector<vector<pair<int, int>>> A;
vector<vector<int>> edge;
vector<int> min_cost;
vector<bool> is_finish;
vector<bool> is_used;
void dijkstra() {
  for (int i = 1; i <= N; ++i) {
    priority_queue<pair<int, int>, vector<pair<int, int>>,
                   greater<pair<int, int>>>
        pq;
    pq.push(pair<int, int>(0, i));
    fill(min_cost.begin(), min_cost.end(), INF);
    min_cost[i] = 0;
    int pre_id = i;
    while (!pq.empty()) {
      pair<int, int> now = pq.top();
      pq.pop();
      int now_cost = now.first;
      int now_id = now.second;
      if (is_finish[now_id]) continue;
      is_finish[now_id] = true;
      if (now_id != pre_id) is_used[edge[pre_id][now_id]] = true;
      for (int j = 0; j < A[now_id].size(); ++j) {
        int next_cost = A[now_id][j].first;
        int next_id = A[now_id][j].second;
        if (now_cost + next_cost < min_cost[next_id]) {
          int edge_id = edge[now_id][next_id];
          min_cost[next_id] = now_cost + next_cost;
          pq.push(pair<int, int>(min_cost[next_id], next_id));
        }
      }
      pre_id = now_id;
    }
  }
}
int main(void) {
  cin >> N >> M;
  A.resize(N + 1);
  edge.resize(N + 1, vector<int>(N + 1));
  min_cost.resize(N + 1);
  is_finish.resize(N + 1, false);
  is_used.resize(M, false);
  for (int i = 0; i < M; ++i) {
    int a, b, cost;
    cin >> a >> b >> cost;
    A[a].push_back(pair<int, int>(cost, b));
    A[b].push_back(pair<int, int>(cost, a));
    edge[a][b] = edge[b][a] = i;
  }
  dijkstra();
  int ans = count(is_used.begin(), is_used.end(), false);
  cout << ans << endl;
  return 0;
}
