#include <bits/stdc++.h>
using namespace std;
const int INF = 1e9;
const long double EPS = 1e-8;
struct Edge {
  int src, dest, rev;
  int cap;
  int cost;
  bool operator<(const Edge &rhs) const { return cost > rhs.cost; }
  Edge(int s, int d) : src(s), dest(d) { ; }
  Edge(int s, int d, int c) : src(s), dest(d), cost(c) { ; }
  Edge(int s, int d, int r, int cp, int cst)
      : src(s), dest(d), rev(r), cap(cp), cost(cst) {
    ;
  }
};
vector<int> dijkstra(const vector<vector<Edge>> &g, int s) {
  int n = g.size();
  vector<int> d(n, INF);
  d[s] = 0;
  priority_queue<Edge> que;
  que.push(Edge(-1, s, 0));
  while (!que.empty()) {
    Edge e = que.top();
    que.pop();
    if (d[e.dest] < e.cost) continue;
    for (Edge f : g[e.dest]) {
      if (d[f.dest] > e.cost + f.cost) {
        d[f.dest] = e.cost + f.cost;
        que.push(Edge(f.src, f.dest, d[f.dest]));
      }
    }
  }
  return d;
}
int main() {
  int N, M;
  cin >> N >> M;
  vector<vector<Edge>> g(N);
  for (int i = 0; i < (int)(M); i++) {
    int a, b, c;
    cin >> a >> b >> c;
    --a;
    --b;
    g[a].push_back(Edge(a, b, c));
    g[b].push_back(Edge(b, a, c));
  }
  vector<vector<int>> d(N);
  for (int i = 0; i < (int)(N); i++) d[i] = dijkstra(g, i);
  int res = 0;
  for (int i = 0; i < (int)(N); i++)
    for (Edge &e : g[i]) {
      int c = e.cost;
      e.cost = INF;
      vector<vector<int>> dtmp(N);
      for (int j = 0; j < (int)(N); j++) dtmp[j] = dijkstra(g, j);
      e.cost = c;
      bool flag = true;
      for (int j = 0; j < (int)(N); j++)
        for (int k = 0; k < (int)(N); k++)
          if (d[j][k] != dtmp[j][k]) flag = false;
      if (flag) ++res;
    }
  res /= 2;
  cout << res << endl;
  return 0;
}
