#include <bits/stdc++.h>
using namespace std;
int POWINT(int x, int n) {
  int ret = 1;
  for (int i = (int)0; i < (int)n; i++) ret *= x;
  return ret;
};
long long POWLL(int x, int n) {
  long long ret = 1;
  for (int i = (int)0; i < (int)n; i++) ret *= x;
  return ret;
};
template <class T>
inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
};
template <class T>
inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
};
const int INF = 1e9 + 7;
const int MAX = 101;
static const int WHITE = 0;
static const int GRAY = 1;
static const int BLACK = 2;
vector<pair<int, int>> adj[MAX];
int color[MAX];
int d[MAX];
int p[MAX];
void dijkstra(int s, int e) {
  priority_queue<pair<int, int>> PQ;
  for (int i = 0; i < MAX; i++) {
    d[i] = INF;
    color[i] = 0;
  }
  d[s] = 0;
  PQ.push(make_pair(0, s));
  color[s] = GRAY;
  while (!PQ.empty()) {
    pair<int, int> f = PQ.top();
    PQ.pop();
    int u = f.second;
    color[u] = BLACK;
    for (int j = 0; j < adj[u].size(); j++) {
      int v = adj[u][j].first;
      if (color[v] == BLACK) continue;
      if ((u == s && v == e) || (u == e && s == v)) continue;
      if (d[v] > d[u] + adj[u][j].second) {
        d[v] = d[u] + adj[u][j].second;
        p[v] = u;
        PQ.push(make_pair(d[v] * (-1), v));
        color[v] = GRAY;
      }
    }
  }
};
struct Edge {
  int from, to, cost;
};
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  int a, b, c;
  vector<Edge> edges(m);
  for (int i = (int)0; i < (int)m; i++) {
    cin >> a >> b >> c;
    a--;
    b--;
    if (a > b) {
      swap(a, b);
    }
    adj[a].push_back(make_pair(b, c));
    adj[b].push_back(make_pair(a, c));
    edges[i] = Edge{a, b, c};
  }
  int ans = 0;
  for (auto e : edges) {
    int from = e.from;
    int to = e.to;
    int c = e.cost;
    dijkstra(from, to);
    int dis = d[to];
    if (dis <= c) ans++;
  }
  cout << ans << endl;
  return 0;
};
