#include <bits/stdc++.h>
using namespace std;
struct Edge {
  int v, id, next;
} edge[100050 * 2];
int e, ft[10050];
int n, m;
int cnt, dfn[10050], low[10050];
int dsu[100050], col[100050], size[100050];
bool flag[100050];
int find_dsu(int k) {
  if (dsu[k] == k)
    return k;
  else
    return dsu[k] = find_dsu(dsu[k]);
}
void merge(int u, int v) {
  u = find_dsu(col[u]);
  v = find_dsu(col[v]);
  if (u == v)
    flag[u] = true;
  else {
    flag[u] |= flag[v];
    dsu[v] = u;
  }
  return;
}
void init_graph() {
  e = 0;
  memset(ft, -1, sizeof(ft));
}
void add_edge(int u, int v, int id) {
  edge[e].v = v;
  edge[e].id = id;
  edge[e].next = ft[u];
  ft[u] = e++;
}
void insert_edge(int u, int v, int id) {
  add_edge(u, v, id);
  add_edge(v, u, id);
}
void dfs(int u, int from_edge) {
  low[u] = dfn[u] = ++cnt;
  for (int i = ft[u]; i != -1; i = edge[i].next) {
    if (edge[i].id == from_edge) continue;
    int v = edge[i].v;
    if (dfn[v] == -1) {
      dfs(v, edge[i].id);
      if (low[v] < dfn[u]) {
        low[u] = min(low[u], low[v]);
        merge(from_edge, edge[i].id);
      } else if (low[v] == dfn[v]) {
        flag[find_dsu(col[edge[i].id])] = true;
      }
    } else if (dfn[v] < dfn[u]) {
      low[u] = min(low[u], dfn[v]);
      merge(edge[i].id, from_edge);
    }
  }
}
int main() {
  while (scanf("%d%d", &n, &m) == 2) {
    init_graph();
    int u, v, c;
    for (int i = 1; i <= m; i++) {
      scanf("%d%d%d", &u, &v, &c);
      insert_edge(u, v, i);
      col[i] = c;
      flag[i] = false;
      dsu[i] = i;
    }
    cnt = 0;
    memset(dfn, -1, sizeof(dfn));
    dfs(1, -1);
    memset(size, 0, sizeof(size));
    for (int i = 1; i <= m; i++) size[col[i]] = 1;
    for (int i = 1; i <= m; i++)
      if (size[i] && i != find_dsu(i)) size[find_dsu(i)] += size[i];
    int ans = 0;
    for (int i = 1; i <= m; i++) {
      if (find_dsu(i) != i || size[i] == 0) continue;
      if (flag[i])
        ans += size[i];
      else
        ans += size[i] - 1;
    }
    printf("%d\n", ans);
  }
}
