#include <bits/stdc++.h>
using namespace std;
constexpr auto INF = 1000000000;
constexpr auto LLINF = 1LL << 62;
constexpr auto mod = 1000000007;
template <class T>
inline bool chmax(T& a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T>
inline bool chmin(T& a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
class unionfind {
  vector<int> par, rank;

 public:
  void init(int N) {
    par.clear();
    rank.clear();
    for (int i = 0; i < N; i++) par.push_back(i);
    for (int i = 0; i < N; i++) rank.push_back(1);
  }
  int root(int x) {
    if (par[x] == x) return x;
    return par[x] = root(par[x]);
  }
  int size(int x) {
    if (par[x] == x) return rank[x];
    return size(par[x]);
  }
  void unite(int x, int y) {
    int rx = root(x);
    int ry = root(y);
    if (rx == ry) return;
    if (rank[rx] < rank[ry]) {
      par[rx] = ry;
      rank[ry] += rank[rx];
    } else {
      par[ry] = rx;
      rank[rx] += rank[ry];
    }
  }
  bool same(int x, int y) { return root(x) == root(y); }
};
int main() {
  int n, m;
  cin >> n >> m;
  vector<pair<int, pair<int, int>>> a(m);
  for (int(i) = 0; (i) < (m); (i)++) {
    cin >> a[i].second.first >> a[i].second.second >> a[i].first;
    a[i].second.first--, a[i].second.second--;
  }
  sort((a).begin(), (a).end());
  unionfind uf;
  uf.init(n);
  int ans = m;
  for (int(i) = 0; (i) < (m); (i)++) {
    if (uf.same(a[i].second.first, a[i].second.second)) continue;
    uf.unite(a[i].second.first, a[i].second.second);
    ans--;
  }
  cout << ans << endl;
}
