#include <bits/stdc++.h>
using namespace std;
template <typename X>
class Graph {
 private:
  int node;
  int edge_num;
  vector<vector<pair<int, X>>> edge;
  vector<vector<pair<int, pair<X, int>>>> edge3;
  vector<vector<int>> rev;
  vector<X> d;
  vector<vector<X>> d_wf;
  vector<bool> visit;
  vector<bool> f;
  vector<int> color;
  vector<vector<int>> edge2;
  const X inf = 1e+9;

 public:
  Graph(int n) {
    node = n;
    edge.resize(node);
  }
  Graph(int n, int m, vector<int> a, vector<int> b) {
    node = n;
    edge_num = m;
    edge2.resize(node);
    for (int i = 0; i < edge_num; ++i) {
      edge2[a[i]].push_back(b[i]);
      edge2[b[i]].push_back(a[i]);
    }
  }
  Graph(int n, int m, vector<int> a, vector<int> b, vector<X> c,
        vector<int> d) {
    node = n;
    edge_num = m;
    edge3.resize(node);
    for (int i = 0; i < edge_num; ++i) {
      edge3[a[i]].push_back({b[i], {c[i], d[i]}});
      edge3[b[i]].push_back({a[i], {c[i], d[i]}});
    }
  }
  void add_edge(int from, int to, X cost) {
    edge[from].push_back(make_pair(to, cost));
  }
  void dijkstra(int s) {
    priority_queue<pair<X, int>, vector<pair<X, int>>, greater<pair<X, int>>>
        pq;
    d.assign(node, inf);
    d[s] = 0;
    pq.push(make_pair(0, s));
    while (!pq.empty()) {
      pair<X, int> p = pq.top();
      pq.pop();
      int v = p.second;
      if (d[v] < p.first) continue;
      for (auto &w : edge3[v]) {
        if (d[w.first] > d[v] + w.second.first) {
          d[w.first] = d[v] + w.second.first;
          pq.push(make_pair(d[w.first], w.first));
        }
      }
    }
  }
  bool bellmanford(int s) {
    d.assign(node, inf);
    d[s] = 0;
    bool flag = true;
    for (int i = 0; i < node; ++i) {
      for (int v = 0; v < node; ++v) {
        if (d[v] == inf) continue;
        for (auto w : edge[v]) {
          if (d[w.first] > d[v] + w.second) {
            d[w.first] = d[v] + w.second;
            if (i == node - 1) {
              flag = false;
            }
          }
        }
      }
    }
    return flag;
  }
  void wf() {
    d_wf.resize(node, vector<X>(node, inf));
    for (int v = 0; v < node; ++v) {
      for (auto w : edge[v]) {
        d_wf[v][w.first] = w.second;
        d_wf[w.first][v] = w.second;
      }
    }
    for (int k = 0; k < node; ++k) {
      for (int i = 0; i < node; ++i) {
        for (int j = 0; j < node; ++j) {
          d_wf[i][j] = min(d_wf[i][j], d_wf[i][k] + d_wf[k][j]);
        }
      }
    }
  }
  void add_rev(int from, int to) { rev[from].push_back(to); }
  void simple_dfs(int v) {
    visit[v] = true;
    f[v] = true;
    for (auto w : rev[v]) {
      if (visit[w]) {
        continue;
      }
      simple_dfs(w);
    }
  }
  void run_dfs(int g) {
    visit.assign(node, false);
    f.assign(node, false);
    f[g] = true;
    simple_dfs(g);
  }
  bool nibu(int v, int c) {
    color[v] = c;
    for (auto w : edge2[v]) {
      if (color[w] == c) return false;
      if (color[w] == 0 && !nibu(w, -c)) return false;
    }
    return true;
  }
  bool solve_nibu() {
    color.assign(node, 0);
    for (int i = 0; i < node; ++i) {
      if (color[i] == 0) {
        if (!nibu(i, 1)) {
          return false;
        }
      }
    }
    return true;
  }
  int get_color(int v) { return color[v]; }
  void check_f() {
    for (int i = 0; i < node; ++i) {
      cout << i << ":" << f[i] << "\n";
    }
  }
  X get_d(int v) { return d[v]; }
  X get_d(int x, int y) { return d_wf[x][y]; }
  vector<bool> get_pass(int s) {
    dijkstra(s);
    vector<bool> pass(node, false);
    for (int i = 0; i < node; ++i) {
      for (auto w : edge3[i]) {
        if (abs(d[i] - d[w.first]) == w.second.first) {
          pass[w.second.second] = true;
        }
      }
    }
    return pass;
  }
};
int main() {
  int n, m;
  cin >> n >> m;
  vector<int> a(m), b(m), c(m), d(m);
  for (int i = 0; i < m; ++i) {
    cin >> a[i] >> b[i] >> c[i];
    a[i]--;
    b[i]--;
    d[i] = i;
  }
  Graph<int> gp(n, m, a, b, c, d);
  vector<bool> path(n, false);
  for (int i = 0; i < n; ++i) {
    vector<bool> tmp = gp.get_pass(i);
    for (int j = 0; j < m; ++j) {
      path[j] = path[j] || tmp[j];
    }
  }
  int cnt = 0;
  for (int i = 0; i < m; ++i) {
    if (!path[i]) cnt++;
  }
  cout << cnt << "\n";
  return 0;
}
