#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll mod = 1e9 + 7;
ll INFL = 1e18;
int INF = 1e9;
int used[100][100] = {0};
int edge_mat[100][100] = {0};
struct edge {
  int to, cost;
};
int main() {
  int M, N;
  int d[100];
  vector<edge> G[100];
  cin >> N >> M;
  for (int i(0); i < M; i++) {
    int a, b, c;
    cin >> a >> b >> c;
    a--;
    b--;
    edge e1;
    e1.to = b;
    e1.cost = c;
    G[a].push_back(e1);
    edge e2;
    e2.to = a;
    e2.cost = c;
    G[b].push_back(e2);
    edge_mat[a][b] = c;
    edge_mat[b][a] = c;
  }
  for (int i(0); i < N; i++) {
    int s = i;
    priority_queue<pair<int, int>, vector<pair<int, int>>,
                   greater<pair<int, int>>>
        q;
    fill(d, d + N, INF);
    d[s] = 0;
    q.push(pair<int, int>(0, s));
    while (!q.empty()) {
      pair<int, int> p = q.top();
      q.pop();
      int v = p.second;
      if (d[v] < p.first) continue;
      for (int i(0); i < G[v].size(); i++) {
        edge e = G[v][i];
        if (d[e.to] > d[v] + e.cost) {
          d[e.to] = d[v] + e.cost;
          q.push(pair<int, int>(d[e.to], e.to));
        }
      }
    }
    for (int i(0); i < N; i++) {
      int now = i;
      int used_node[100] = {0};
      while (now != s) {
        used_node[now] = 1;
        for (int j(0); j < G[now].size(); j++) {
          int kouho = G[now][j].to;
          if (d[now] == d[kouho] + edge_mat[now][kouho] &&
              used_node[kouho] == 0) {
            used[now][kouho] = 1;
            now = kouho;
            break;
          }
        }
      }
    }
  }
  int ans(0);
  for (int i(0); i < N; i++) {
    for (int j(i + 1); j < N; j++) {
      if (used[i][j] == 0 && edge_mat[i][j] != 0) ans++;
    }
  }
  cout << ans << endl;
}
