#include <bits/stdc++.h>
using ll = long long;
using namespace std;
vector<int> dijkstra(int n, int st, const multimap<int, pair<int, int>>& graph);
int main() {
  int n, m;
  cin >> n >> m;
  multimap<int, pair<int, int>> graph;
  for (int i = (int)(0); i < (int)(m); ++i) {
    int a, b, c;
    cin >> a >> b >> c;
    graph.insert({a - 1, {b - 1, c}});
    graph.insert({b - 1, {a - 1, c}});
  }
  vector<vector<int>> minNode;
  minNode.reserve(n);
  for (int st = (int)(0); st < (int)(n); ++st) {
    minNode.emplace_back(dijkstra(n, st, graph));
  }
  int count = m;
  set<pair<int, int>> memo;
  for (auto& edge : graph) {
    const int defo = edge.second.second;
    edge.second.second = 1e7;
    bool flg = true;
    for (int st = (int)(0); st < (int)(n); ++st) {
      if (minNode[st] != dijkstra(n, st, graph)) {
        flg = false;
        break;
      }
    }
    if (!flg) {
      edge.second.second = defo;
      memo.emplace(edge.first, edge.second.first);
      if (memo.find({edge.second.first, edge.first}) == memo.end()) {
        --count;
      }
    }
  }
  cout << count << endl;
}
vector<int> dijkstra(int n, int st,
                     const multimap<int, pair<int, int>>& graph) {
  vector<int> node(n, 1e7);
  node[st] = 0;
  list<int> q{st};
  while (!q.empty()) {
    const int now = *(q.begin());
    const auto range = graph.equal_range(now);
    for (auto itr = range.first; itr != range.second; ++itr) {
      const auto p = itr->second;
      if (node[now] + p.second < node[p.first]) {
        node[p.first] = node[now] + p.second;
        q.emplace_back(p.first);
      }
    }
    q.pop_front();
    q.sort();
  }
  return node;
}
