#include <bits/stdc++.h>
using namespace std;
const int INF = 1e9 + 10, MN = 1e5 + 10;
int n, m;
int es[MN], ee[MN], col[MN];
vector<pair<int, int> > adj[MN];
int par[MN], deg[MN], head[MN], prv[MN], from[MN], to[MN], cap[MN], E;
int cur_e[MN], h[MN];
bool mk[MN];
void add_edge(int u, int v, int Cap) {
  from[E] = u, to[E] = v, cap[E] = Cap;
  prv[E] = head[u], head[u] = E++;
  from[E] = v, to[E] = u, cap[E] = 0;
  prv[E] = head[v], head[v] = E++;
}
void dfs1(int s) {
  mk[s] = true;
  for (auto x : adj[s])
    if (!mk[x.first]) {
      par[x.first] = x.second;
      h[x.first] = h[s] + 1;
      dfs1(x.first);
    }
}
int L, R, q[MN];
int dfs(int st, int en, int Cur) {
  if (st == en) {
    return Cur;
  }
  int ret = 0;
  for (int &e = cur_e[st]; ~e; e = prv[e])
    if (cap[e] && h[to[e]] == h[from[e]] + 1) {
      if (Cur == 0) break;
      int t = dfs(to[e], en, min(Cur, cap[e]));
      if (!t) continue;
      cap[e] -= t;
      cap[e ^ 1] += t;
      ret += t;
      Cur -= t;
    }
  return ret;
}
int max_flow(int st, int en) {
  L = R = 0;
  q[R++] = st;
  fill(mk, mk + n, false);
  fill(h, h + n, 0);
  mk[st] = true;
  while (L < R) {
    int v = q[L++];
    for (int e = head[v]; ~e; e = prv[e])
      if (cap[e]) {
        int u = to[e];
        if (mk[u]) continue;
        h[u] = h[v] + 1;
        mk[u] = true;
        q[R++] = u;
      }
  }
  for (int i = 0; i < n; ++i) cur_e[i] = head[i];
  int ret = dfs(st, en, INF);
  if (ret == 0) return 0;
  return ret + max_flow(st, en);
}
int main() {
  ios_base ::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  memset(prv, -1, sizeof prv);
  memset(head, -1, sizeof head);
  cin >> n >> m;
  for (int i = 0; i < m; ++i) {
    cin >> es[i] >> ee[i] >> col[i];
    --es[i], --ee[i], --col[i];
    adj[es[i]].push_back({ee[i], i});
    adj[ee[i]].push_back({es[i], i});
  }
  par[0] = -1;
  dfs1(0);
  for (int i = 0; i < m; ++i)
    if (h[ee[i]] < h[es[i]]) swap(es[i], ee[i]);
  memset(mk, 0, sizeof mk);
  int sz = m, Num = 0;
  for (int i = 0; i < m; ++i) {
    if (h[ee[i]] - h[es[i]] == 1) continue;
    vector<int> cy;
    cy.push_back(col[i]);
    int cur = ee[i];
    mk[i] = true;
    while (cur != es[i]) {
      cy.push_back(col[par[cur]]);
      mk[par[cur]] = true;
      cur = es[par[cur]];
    }
    ++Num;
    for (auto x : cy) {
      add_edge(sz, x, 1);
      ++deg[x];
    }
    sz++;
  }
  for (int i = 0; i < m; ++i)
    if (!mk[i]) {
      add_edge(sz++, col[i], 0);
      ++deg[col[i]];
    }
  for (int i = m; i < sz; ++i) add_edge(sz, i, 1);
  int st = sz++;
  for (int i = 0; i < m; ++i)
    if (deg[i]) add_edge(i, sz, deg[i] - 1);
  int en = sz++;
  int X = 0;
  for (int i = 0; i < m; ++i)
    if (deg[i]) X++;
  n = sz;
  cout << X - (Num - max_flow(st, en)) << '\n';
  return 0;
}
