#include <bits/stdc++.h>
using namespace std;
template <typename T>
void read(T &t) {
  t = 0;
  char ch = getchar();
  int f = 1;
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  do {
    (t *= 10) += ch - '0';
    ch = getchar();
  } while ('0' <= ch && ch <= '9');
  t *= f;
}
template <typename T>
void write(T t) {
  if (t < 0) {
    putchar('-');
    write(-t);
    return;
  }
  if (t > 9) write(t / 10);
  putchar('0' + t % 10);
}
template <typename T>
void writeln(T t) {
  write(t);
  puts("");
}
const int maxn = (6e5) + 10;
int n, m, w[maxn], bel[maxn], fa[maxn];
vector<pair<int, int> > g[maxn / 2];
int dep[maxn];
vector<int> a[maxn];
int tot, mk[maxn], vis[maxn], Vis[maxn];
int lsh[maxn], N;
void dfs(int u, int p) {
  dep[u] = dep[p] + 1;
  fa[u] = p;
  Vis[u] = 1;
  for (int i = 0, v; i < g[u].size(); i++) {
    v = g[u][i].first;
    if (v == p) continue;
    if (dep[v]) {
      if (dep[v] < dep[u]) {
        tot++;
        a[tot].push_back(g[u][i].second);
        int x = u;
        while (x != v) {
          a[tot].push_back(w[x]);
          bel[x] = tot;
          x = fa[x];
        }
      }
    } else {
      w[v] = g[u][i].second;
      dfs(v, u);
    }
  }
}
int f[maxn], NN, re[maxn];
int find(int x) {
  if (f[x] == x) return x;
  return f[x] = find(f[x]);
}
void merge(int x, int y) { f[find(x)] = find(y); }
int deg[maxn];
namespace Dinic {
const int INF = 1e9;
int s, t, cur[maxn];
int level[maxn], tot;
int ans, flow[maxn * 6];
int head[maxn], nxt[maxn * 6];
int to[maxn * 6];
queue<int> q;
void Add_edge(int a, int b, int c) {
  tot++;
  nxt[tot] = head[a];
  head[a] = tot;
  to[tot] = b;
  flow[tot] = c;
}
void add_edge(int a, int b, int c) {
  Add_edge(a, b, c);
  Add_edge(b, a, 0);
}
bool bfs() {
  q = queue<int>();
  for (int i = 1; i <= t; i++) level[i] = -1, cur[i] = head[i];
  q.push(s);
  level[s] = 0;
  while (!q.empty()) {
    int a = q.front(), b;
    q.pop();
    for (register int i = head[a]; i; i = nxt[i]) {
      b = to[i];
      if (flow[i] > 0 && level[b] == -1) {
        level[b] = level[a] + 1;
        q.push(b);
      }
    }
  }
  return level[t] != -1;
}
int dfs(int x, int rest) {
  if (x == t) return rest;
  int used = 0;
  for (register int i = cur[x]; i; i = nxt[i]) {
    cur[x] = i;
    int y = to[i];
    if (flow[i] > 0 && level[y] == level[x] + 1) {
      int tflow = dfs(y, min(flow[i], rest - used));
      used += tflow;
      flow[i] -= tflow;
      flow[i ^ 1] += tflow;
      if (rest - used == 0) break;
    }
  }
  if (!used) level[x] = -1;
  return used;
}
int solve() {
  int res = 0;
  while (bfs()) res += dfs(s, INF);
  return res;
}
};  // namespace Dinic
int main() {
  Dinic::tot = 1;
  read(n), read(m);
  int x, y, z;
  for (int i = 1; i <= m; i++) {
    read(x), read(y), read(z);
    g[x].push_back(make_pair(y, z)), g[y].push_back(make_pair(x, z));
    lsh[++N] = z;
  }
  sort(lsh + 1, lsh + N + 1);
  N = unique(lsh + 1, lsh + N + 1) - lsh - 1;
  for (int i = 1; i <= n; i++)
    for (int j = 0; j < g[i].size(); j++)
      g[i][j].second = lower_bound(lsh + 1, lsh + N + 1, g[i][j].second) - lsh;
  for (int i = 1; i <= n; i++)
    if (!Vis[i]) dfs(i, 0);
  for (int i = 1; i <= tot + N; i++) f[i] = i;
  for (int i = 1; i <= tot; i++) {
    for (int x : a[i]) {
      if (vis[x] == i) mk[x] = 1;
      vis[x] = i;
      merge(x, i + N);
    }
  }
  for (int i = 2; i <= n; i++)
    if (!bel[i]) {
      mk[find(w[i])] = 1;
    }
  for (int i = 1; i <= N; i++)
    if (mk[i]) mk[find(i)] = 1;
  for (int i = 1; i <= tot; i++)
    if (!mk[find(i + N)]) {
      for (int x : a[i]) re[++NN] = x;
    }
  sort(re + 1, re + NN + 1);
  NN = unique(re + 1, re + NN + 1) - re - 1;
  int cnt = 0;
  for (int i = 1; i <= tot; i++)
    if (!mk[find(i + N)]) {
      cnt++;
      for (int x : a[i]) {
        int y = lower_bound(re + 1, re + NN + 1, x) - re;
        deg[y]++;
        Dinic::add_edge(y, cnt + NN, 1);
      }
    }
  Dinic::s = cnt + NN + 1, Dinic::t = cnt + NN + 2;
  for (int i = 1; i <= cnt; i++) Dinic::add_edge(i + NN, Dinic::t, 1);
  for (int i = 1; i <= NN; i++) Dinic::add_edge(Dinic::s, i, deg[i] - 1);
  int ans = cnt - Dinic::solve();
  printf("%d\n", N - ans);
  return 0;
}
