#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3FFFFFFF;
int n, m;
vector<vector<vector<int>>> e;
vector<vector<int>> par;
vector<bool> used;
vector<vector<int>> blk;
struct Dinic {
  struct edge {
    int t, c, r;
    edge() {}
    edge(int _t, int _c, int _r) : t(_t), c(_c), r(_r) {}
  };
  int n;
  vector<vector<edge>> E;
  vector<bool> used;
  void add(int u, int v, int c) {
    E[u].push_back(edge(v, c, E[v].size()));
    E[v].push_back(edge(u, 0, E[u].size() - 1));
  }
  Dinic(int _n) : n(_n), E(_n) {}
  edge &rev(const edge &e) { return E[e.t][e.r]; }
  int dfs(int s, int t, int num) {
    if (s == t || num == 0) return num;
    used[s] = true;
    int res = 0;
    for (edge &cur : E[s]) {
      if (cur.c > 0 && !used[cur.t]) {
        int can = min(cur.c, num);
        int flow = dfs(cur.t, t, can);
        res += flow;
        rev(cur).c += flow;
        cur.c -= flow;
        num -= flow;
      }
    }
    return res;
  }
  int sol(int s, int t) {
    int res = 0, tmp;
    while (true) {
      used = vector<bool>(n, false);
      tmp = dfs(s, t, INF);
      if (tmp <= 0) break;
      res += tmp;
    }
    return res;
  }
};
void dfs(int x) {
  used[x] = true;
  for (int i = 0; i < e[x].size(); i++) {
    int u = e[x][i][0];
    if (u == par[x][0] || e[x][i][1] == -1) continue;
    if (!used[u]) {
      par[u] = {x, i};
      dfs(u);
    } else {
      blk.push_back({});
      blk.back().push_back(e[x][i][1]);
      e[x][i][1] = -1;
      e[u][e[x][i][2]][1] = -1;
      int now = x;
      while (now != u) {
        blk.back().push_back(e[par[now][0]][par[now][1]][1]);
        e[par[now][0]][par[now][1]][1] = -1;
        e[now][e[par[now][0]][par[now][1]][2]][1] = -1;
        now = par[now][0];
      }
    }
  }
}
int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  e.resize(n + 1);
  for (int i = 0; i < m; i++) {
    int u, v, c;
    scanf("%d%d%d", &u, &v, &c);
    e[u].push_back({v, c, (int)e[v].size()});
    e[v].push_back({u, c, (int)e[u].size() - 1});
  }
  par.assign(n + 1, {-1, -1});
  used.assign(n + 1, false);
  dfs(1);
  for (int i = 1; i <= n; i++)
    for (int j = 0; j < e[i].size(); j++)
      if (e[i][j][0] < i && e[i][j][1] != -1)
        blk.push_back({}), blk.back().push_back(e[i][j][1]);
  map<int, int> cs;
  for (vector<int> &v : blk)
    for (int t : v) cs[t];
  int a = 1;
  for (auto it = cs.begin(); it != cs.end(); it++, a++) it->second = a;
  int b = blk.size(), N = (--a) + b + 2;
  Dinic D(N);
  for (int i = 0; i < b; i++) {
    D.add(a + 1 + i, N - 1, max(1, (int)blk[i].size() - 1));
    for (int t : blk[i]) D.add(cs[t], a + 1 + i, 1);
  }
  for (int i = 1; i <= a; i++) D.add(0, i, 1);
  printf("%d\n", D.sol(0, N - 1));
}
