#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using pii = pair<i64, i64>;
template <class A, class B>
inline bool chmax(A &a, const B &b) {
  return b > a ? a = b, 1 : 0;
}
template <class A, class B>
inline bool chmin(A &a, const B &b) {
  return b < a ? a = b, 1 : 0;
}
constexpr const int INF = 0x3f3f3f3f;
constexpr const i64 LINF = 0x3f3f3f3f3f3f3f3fLL;
constexpr const int MOD = int(1e9) + 7;
namespace {
int N, M;
vector<pii> G[105];
int dist[105];
int prev[105];
bool used[1005];
map<pii, int> edgeid;
void dijkstra(int start) {
  priority_queue<pii, vector<pii>, greater<pii> > pq;
  memset(dist, INF, sizeof(dist));
  pq.emplace(0, start);
  dist[start] = 0;
  while (!pq.empty()) {
    const int c = pq.top().first;
    const int u = pq.top().second;
    pq.pop();
    if (dist[u] < c) continue;
    for (auto e : G[u]) {
      const int ncost = c + e.first;
      const int nxt = e.second;
      if (chmin(dist[nxt], ncost)) {
        pq.emplace(ncost, nxt);
        prev[nxt] = u;
      }
    }
  }
  return;
}
int getID(int s, int t) {
  if (s > t) swap(s, t);
  return edgeid[pii(s, t)];
}
void setID(int s, int t, int id) {
  if (s > t) swap(s, t);
  edgeid[pii(s, t)] = id;
  return;
}
signed __() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  cin >> N >> M;
  for (int i = 0; i < M; ++i) {
    int a, b, c;
    cin >> a >> b >> c;
    G[a].push_back(pii(c, b));
    G[b].push_back(pii(c, a));
    setID(a, b, i);
  }
  for (int i = 1; i <= N; ++i) {
    dijkstra(i);
    for (int u = 1; u <= N; ++u) {
      const int v = prev[u];
      used[getID(u, v)] = true;
    }
  }
  int ans = 0;
  for (int i = 0; i < M; ++i) {
    if (!used[i]) ++ans;
  }
  cout << ans << '\n';
  return 0;
}
}  // namespace
signed main() {
  __();
  return 0;
}
