#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<ll, ll>;
using TP = tuple<ll, ll, ll>;
ll MOD = 1e9 + 7;
const int INF = 1e6;
const ll LINF = (ll)1e18;
using Graph = vector<vector<P>>;
int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  map<string, int> d;
  int N, M;
  cin >> N >> M;
  Graph G(N);
  vector<vector<ll>> mp(N, vector<ll>(N, LINF));
  vector<vector<ll>> mpo1(N, vector<ll>(N, LINF));
  vector<vector<ll>> mpo2(N, vector<ll>(N, LINF));
  for (int(i) = 0; (i) < (M); (i)++) {
    ll a, b, c;
    cin >> a >> b >> c;
    a--;
    b--;
    mp[a][b] = c;
    G[a].push_back(make_pair(b, c));
  }
  mpo1 = mp;
  mpo2 = mp;
  for (int(k) = 0; (k) < (N); (k)++) {
    for (int(i) = 0; (i) < (N); (i)++) {
      for (int(j) = 0; (j) < (N); (j)++) {
        mp[i][j] = min(mp[i][j], mp[i][k] + mp[k][j]);
      }
    }
  }
  vector<bool> ans(N, false);
  stack<tuple<ll, ll, vector<P>>> st;
  ll cur;
  ll len;
  for (int(i) = 0; (i) < (N); (i)++) {
    for (int(j) = 0; (j) < (N); (j)++) {
      if (i != j) {
        ll sumlen = 0;
        vector<P> used;
        st.push(make_tuple(i, 0, used));
        while (!st.empty()) {
          vector<P> used2;
          tie(cur, len, used2) = st.top();
          st.pop();
          sumlen += len;
          if (cur == j) {
            if (sumlen == mp[i][j]) {
              for (int k = 0; k < used2.size(); k++) {
                mpo1[used2[k].first][used2[k].second] = -1;
              }
            }
          } else {
            for (int k = 0; k < G[cur].size(); k++) {
              vector<P> used3 = used2;
              used3.push_back(make_pair(cur, G[cur][k].first));
              st.push(make_tuple(G[cur][k].first, G[cur][k].second, used3));
            }
          }
        }
      }
    }
  }
  ll cnt = 0;
  for (int(i) = 0; (i) < (N); (i)++) {
    for (int(j) = 0; (j) < (N); (j)++) {
      if (mpo2[i][j] != LINF && mpo1[i][j] != -1) {
        cnt++;
      }
    }
  }
  cout << cnt << endl;
  return 0;
}
