#include <bits/stdc++.h>
using namespace std;
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
const long long mod = 1000000007;
const long long inf = long long(1e9);
const long long half_inf = long long(1e5);
const long long ll_inf = long long(1e9) * long long(1e9);
struct edge {
  int u, v, cost;
};
class UnionFind {
 public:
  vector<long long> par;
  vector<long long> rank;
  explicit UnionFind(unsigned int n) {
    par.resize(n);
    rank.resize(n);
    for (long long i = 0; i < (long long)(n); i++) {
      par[i] = i;
      rank[i] = 0;
    }
  }
  long long find(long long x) {
    if (par[x] == x) {
      return x;
    } else {
      return par[x] = find(par[x]);
    }
  }
  void unite(long long x, long long y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    if (rank[x] < rank[y]) {
      par[x] = y;
    } else {
      par[y] = x;
      if (rank[x] == rank[y]) rank[x]++;
    }
  }
  bool is_same(long long x, long long y) { return find(x) == find(y); }
};
bool comp(const edge &e1, const edge &e2) { return e1.cost < e2.cost; }
const long long MAX_E = half_inf;
long long V, E;
edge es[MAX_E];
long long kruskal() {
  sort(es, es + E, comp);
  UnionFind u = UnionFind(V);
  long long res = 0;
  int ans = 0;
  for (long long i = 0; i < (long long)(E); i++) {
    edge e = es[i];
    if (!u.is_same(e.u, e.v)) {
      u.unite(e.u, e.v);
      res += e.cost;
    } else {
      ans++;
    }
  }
  return ans;
}
void solve() { cout << kruskal() << endl; }
int main() {
  cin >> V >> E;
  for (long long i = 0; i < (long long)(E); i++) {
    int a, b, c;
    cin >> a >> b >> c;
    edge e = {a, b, c};
    es[i] = e;
  }
  solve();
  return 0;
}
