#include <bits/stdc++.h>
using namespace std;
inline void read(int &x) {
  x = 0;
  char ch = getchar(), flag = 0;
  while ((ch > '9' || ch < '0') && ch != '-') ch = getchar();
  if (ch == '-') flag = 1, ch = getchar();
  while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
  if (flag) x = -x;
}
inline void read(int &x, int &y) { read(x), read(y); }
inline void read(int &x, int &y, int &z) { read(x), read(y), read(z); }
const int N = 20005, inf = 1e9 + 7, mod = 20000;
int n, m, up[N], cup[N], cnt, si[N], num[N], dep[N], use[N];
vector<int> g[N], f[N], s[N];
bool vis[N];
struct node {
  int to, next, v;
} p[N << 4];
int S, T, head[N], st[N], tot, ans;
inline void add(int x, int y, int z) {
  p[tot].to = y;
  p[tot].next = head[x];
  p[tot].v = z;
  head[x] = tot++;
  p[tot].to = x;
  p[tot].next = head[y];
  p[tot].v = 0;
  head[y] = tot++;
}
queue<int> q;
inline bool bfs(int x) {
  memset(st, 0, sizeof(st));
  st[x] = 1;
  q.push(x);
  while (!q.empty()) {
    int x = q.front();
    q.pop();
    for (int i = head[x]; ~i; i = p[i].next) {
      int y = p[i].to, v = p[i].v;
      if (!v || st[y]) continue;
      st[y] = st[x] + 1;
      q.push(y);
    }
  }
  return st[T] > 0;
}
inline int dfs(int x, int f) {
  int r = 0;
  if (x == T) return f;
  for (int i = head[x]; ~i; i = p[i].next) {
    int y = p[i].to, v = p[i].v, tmp;
    if (!v || st[y] != st[x] + 1) continue;
    tmp = dfs(y, min(f - r, v));
    r += tmp;
    p[i].v -= tmp;
    p[i ^ 1].v += tmp;
    if (r == f) break;
  }
  if (!r) st[x] = -1;
  return r;
}
inline void dinic() {
  int t;
  while (bfs(S))
    while (t = dfs(S, inf)) ans += t;
  printf("%d\n", ans);
}
inline void Add(int x, int y, int z) {
  g[x].push_back(y);
  f[x].push_back(z);
  g[y].push_back(x);
  f[y].push_back(z);
  vis[x] = vis[y] = 1;
}
inline void Dfs(int x, int fa) {
  vis[x] = 1;
  for (int i = 0; i < g[x].size(); i++) {
    int y = g[x][i], z = f[x][i];
    if (y == fa) continue;
    if (vis[y] && dep[y] < dep[x]) {
      cnt++;
      s[cnt].push_back(z);
      si[z]--;
      int k = x, o = 0;
      while (k != y) {
        si[cup[k]]--;
        s[cnt].push_back(cup[k]);
        k = up[k];
      }
      continue;
    }
    if (vis[y]) continue;
    cup[y] = z;
    up[y] = x;
    dep[y] = dep[x] + 1;
    Dfs(y, x);
  }
}
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= m; i++) {
    int x, y, z;
    scanf("%d%d%d", &x, &y, &z);
    Add(x, y, z);
    si[z]++;
    use[z]++;
  }
  for (int i = 1; i <= n; i++)
    if (vis[i]) {
      memset(vis, 0, sizeof(vis));
      Dfs(i, -1);
      break;
    }
  memset(head, -1, sizeof(head));
  S = 0;
  T = cnt + 1;
  for (int i = 1; i <= m; i++)
    if (!si[i] && use[i])
      T++;
    else if (use[i])
      ans++;
  int CNT = cnt;
  for (int i = 1; i <= m; i++)
    if (!si[i] && use[i]) add(num[i] = ++CNT, T, 1);
  for (int i = 1; i <= cnt; i++) {
    bool isok = 1;
    for (int j = 0; j < s[i].size(); j++)
      if (si[s[i][j]]) isok = 0;
    add(S, i, s[i].size() - 1);
    for (int j = 0; j < s[i].size(); j++)
      if (num[s[i][j]]) add(i, num[s[i][j]], 1);
  }
  dinic();
  return 0;
}
