#include <bits/stdc++.h>
using namespace std;
const int INF = (int)(1e7 + 5);
const int MAX_N = (int)(100 + 5);
const int MAX_M = (int)(1000 + 5);
class elem {
 public:
  int cost;
  vector<int> path;
  elem(int cost, vector<int> path) {
    this->cost = cost;
    this->path = path;
  }
};
int n, m;
vector<elem> d[MAX_N];
bool used[MAX_N];
int ans;
int main(void) {
  scanf("%d %d", &n, &m);
  vector<int> tmp = {-1};
  for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= n; ++j) {
      d[i].push_back(elem(INF, tmp));
    }
  vector<int> emp = {};
  for (int i = 1; i <= n; ++i) d[i][i] = elem(0, emp);
  for (int i = 1; i <= m; ++i) {
    int a, b, c;
    scanf("%d %d %d", &a, &b, &c);
    vector<int> cur = {i};
    d[a][b] = elem(c, cur);
    d[b][a] = elem(c, cur);
  }
  for (int k = 1; k <= n; ++k)
    for (int i = 1; i <= n; ++i)
      for (int j = 1; j <= n; ++j) {
        if (d[i][j].cost > d[i][k].cost + d[k][k].cost) {
          d[i][j].cost = d[i][k].cost + d[k][k].cost;
          vector<int> newpath = d[i][k].path;
          newpath.insert(newpath.end(), d[k][j].path.begin(),
                         d[k][j].path.end());
          d[i][j].path = newpath;
        }
      }
  fill(used, used + m + 3, false);
  for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= n; ++j) {
      for (int l = 0; l < d[i][j].path.size(); ++l) {
        used[d[i][j].path[l]] = true;
      }
    }
  ans = 0;
  for (int i = 1; i <= m; ++i) {
    if (!used[i]) ans += 1;
  }
  printf("%d\n", ans);
  return 0;
}
