#include <bits/stdc++.h>
using namespace std;
int fx[4] = {1, -1, 0, 0};
int fy[4] = {0, 0, 1, -1};
const double PI = acos(-1.0);
const double EPS = 1e-6;
const int MOD = (int)1e9 + 7;
const int maxn = (int)2e5 + 5;
struct edge {
  int u, v, w;
};
vector<edge> graph, output;
int parent[maxn], mstValue = 0;
int n, e;
bool compare(edge a, edge b) { return a.w < b.w; }
int Find(int node) {
  if (parent[node] == node) return node;
  return parent[node] = Find(parent[node]);
}
void initPar(int node) {
  for (int i = 0; i <= node; i++) {
    parent[i] = i;
  }
}
void minimumSpaningTree(int node) {
  sort(graph.begin(), graph.end(), compare);
  initPar(node);
  int cnt = 0;
  for (int i = 0; i < (int)graph.size(); i++) {
    int uPr = Find(graph[i].u);
    int vPr = Find(graph[i].v);
    if (uPr != vPr) {
      if (cnt == n - 1) break;
      output.push_back(graph[i]);
      mstValue += graph[i].w;
      parent[uPr] = vPr;
      cnt++;
    }
  }
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(NULL);
  cout.tie(NULL);
  cin >> n >> e;
  for (int i = 0; i < e; i++) {
    int u, v, w;
    cin >> u >> v >> w;
    edge input;
    input.u = u;
    input.v = v;
    input.w = w;
    graph.push_back(input);
  }
  minimumSpaningTree(n);
  cout << graph.size() - output.size() << endl;
  return 0;
}
