#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
const int INF = 1 << 29;
const double EPS = 1e-9;
const ll MOD = 1000000007;
const int dx[] = {1, 0, -1, 0}, dy[] = {0, -1, 0, 1};
const int MAX_N = 110;
int dist[MAX_N][MAX_N];
int N, M;
void init() {
  for (int i = 0; i < MAX_N; i++) {
    for (int j = 0; j < MAX_N; j++) {
      dist[i][j] = INF;
      if (i == j) {
        dist[i][j] = 0;
      }
    }
  }
}
struct node {
  int v, d;
  node(int v, int d) : v(v), d(d) {}
  bool operator<(const node &n) const { return d > n.d; }
};
struct edge {
  int to, d;
};
int V;
vector<edge> G[MAX_N];
int cost[MAX_N];
set<pii> tmp;
void dijkstra(int s) {
  memset(cost, -1, sizeof(cost));
  priority_queue<node> que;
  que.push(node(s, 0));
  while (!que.empty()) {
    int v = que.top().v, d = que.top().d;
    que.pop();
    if (cost[v] >= 0 and cost[v] <= d) continue;
    cost[v] = d;
    for (int i = 0; i < G[v].size(); i++) {
      int next = G[v][i].to;
      if (dist[next][s] == d + G[v][i].d) {
        tmp.emplace(make_pair(min(next, v), max(next, v)));
      }
      que.push(node(G[v][i].to, d + G[v][i].d));
    }
  }
}
int main() {
  init();
  cin >> N >> M;
  for (int i = 0; i < M; i++) {
    int a, b, c;
    cin >> a >> b >> c;
    a--, b--;
    dist[a][b] = c;
    dist[b][a] = c;
    G[a].push_back(edge{b, c});
    G[b].push_back(edge{a, c});
  }
  for (int k = 0; k < N; k++) {
    for (int i = 0; i < N; i++) {
      for (int j = 0; j < N; j++) {
        dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
      }
    }
  }
  for (int i = 0; i < N; i++) {
    dijkstra(0);
  }
  cout << M - tmp.size() << endl;
  return 0;
}
