#include <bits/stdc++.h>
using namespace std;
class union_find_tree {
 private:
  int32_t N;
  vector<int32_t> parents, rank, node_cnt;

 public:
  void init(int32_t n) {
    parents.resize(n);
    for (int32_t i = 0; i < n; i++) parents[i] = i;
    rank.resize(n, 0);
    node_cnt.resize(n, 1);
    N = n;
  }
  int32_t find(int32_t x) {
    if (parents[x] == x) {
      return x;
    } else {
      parents[x] = find(parents[x]);
      return parents[x];
    }
  }
  void unite(int32_t x, int32_t y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    if (rank[x] < rank[y]) {
      parents[x] = y;
      node_cnt[y] += node_cnt[x];
    } else {
      parents[y] = x;
      node_cnt[x] += node_cnt[y];
      if (rank[x] == rank[y]) rank[x]++;
    }
  }
  bool same(int32_t x, int32_t y) { return find(x) == find(y); }
  int32_t get_parent(int32_t x) { return parents[x]; }
  bool is_root(int32_t x) { return parents[x] == x; }
  int32_t number_of_groups() {
    int32_t cnt = 0;
    for (int32_t i = 0; i < N; i++)
      if (is_root(i)) cnt++;
    return cnt;
  }
  int32_t group_size(int32_t x) { return node_cnt[find(x)]; }
};
struct edge {
  int32_t start, end, cost;
};
int main() {
  int32_t N, M;
  scanf("%d%d", &N, &M);
  struct edge edges[1000];
  for (int32_t i = 0; i < M; i++) {
    scanf("%d%d%d", &edges[i].start, &edges[i].end, &edges[i].cost);
    edges[i].start--;
    edges[i].end--;
  }
  sort(edges, edges + M, [](struct edge left, struct edge right) -> bool {
    return left.cost < right.cost;
  });
  union_find_tree uft;
  uft.init(N);
  int32_t res = 0;
  for (int32_t i = 0; i < M; i++) {
    if (uft.same(edges[i].start, edges[i].end))
      res++;
    else
      uft.unite(edges[i].start, edges[i].end);
  }
  printf("%d\n", res);
  return 0;
}
