#include <bits/stdc++.h>
using namespace std;
template <class T>
using vec = vector<T>;
template <class T>
using heap = priority_queue<T>;
template <class T>
using minheap = priority_queue<T, vec<T>, greater<T>>;
using lint = long long;
using ulint = unsigned long long;
using ld = long double;
using vi = vec<int>;
using vvi = vec<vi>;
using vvvi = vec<vvi>;
using pii = pair<int, int>;
using vs = vec<string>;
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << p.first << " " << p.second;
}
template <class T, class U>
istream &operator>>(istream &is, pair<T, U> &p) {
  return is >> p.first >> p.second;
}
const int INF{1001001001};
const lint LINF{1001001001001001001ll};
const int MOD{(int)1e9 + 7};
const double EPS{1e-9};
const double PI{acos(-1)};
const int dx[]{0, 1, 0, -1, 1, -1, 1, -1}, dy[]{1, 0, -1, 0, 1, -1, -1, 1};
inline bool inside(int y, int x, int h, int w) {
  return y >= 0 && x >= 0 && y < h && x < w;
}
template <class T>
inline bool chmin(T &a, const T &b) {
  if (a > b) a = b;
  return a > b;
}
template <class T>
inline bool chmax(T &a, const T &b) {
  if (a < b) a = b;
  return a < b;
}
template <class T>
inline void print(const T &x) {
  cout << x << '\n';
}
template <class T>
inline void print(const vec<T> &v, string d = "\n") {
  for (lint i = (0); i < (lint)(v.size()); i += (1))
    cout << v[i] << (i == v.size() - 1 ? "\n" : d);
}
template <class T = int>
inline T in() {
  T x;
  cin >> x;
  return x;
}
template <class T = string>
vec<T> split(const string &s, char d = ',') {
  vec<T> v;
  stringstream ss(s);
  for (string b; getline(ss, b, d);) {
    stringstream conv(b);
    T t;
    conv >> t;
    v.emplace_back(t);
  }
  return v;
}
struct pre_ {
  pre_() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(12);
  }
} pre__;
int cost[110][110];
int d[110];
bool used[110];
int n, m;
int res;
void dijkstra(int s) {
  fill(begin(d), end(d), INF);
  fill(begin(used), end(used), false);
  vec<int> pre(110, -1);
  d[s] = 0;
  while (true) {
    int v = -1;
    for (lint u = (0); u < (lint)(n); u += (1)) {
      if (!used[u] && v == -1 || d[u] < d[v]) v = u;
    }
    if (v == -1) break;
    used[v] = true;
    for (lint u = (0); u < (lint)(n); u += (1)) {
      if (d[u] > d[v] + cost[v][u]) {
        d[u] = d[v] + cost[v][u];
        pre[u] = v;
      }
    }
  }
  for (lint i = (0); i < (lint)(n); i += (1)) {
    int t = i;
    for (; t != -1; t = pre[t]) res++;
    res--;
  }
}
signed main() {
  for (lint i = (0); i < (lint)(110); i += (1))
    for (lint j = (0); j < (lint)(110); j += (1)) cost[i][j] = INF;
  cin >> n >> m;
  for (lint i = (0); i < (lint)(m); i += (1)) {
    int a, b, c;
    cin >> a >> b >> c;
    a--;
    b--;
    cost[a][b] = c;
    cost[b][a] = c;
    cerr << " hoge" << endl;
  }
  for (lint i = (0); i < (lint)(n); i += (1)) dijkstra(i);
  print(m - res);
}
