#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 100002;
const int INF = 1e9;
struct edge {
  int u, v, w;
  edge() {}
  edge(int u, int v, int w) : u(u), v(v), w(w) {}
  bool operator==(const edge &e) { return u == e.u && v == e.v && w == e.w; }
};
int n, m, nBCC, low[MAX_N], num[MAX_N];
vector<int> color[MAX_N];
vector<edge> g[MAX_N];
int nEdge, timer, source, target, c[MAX_N], f[MAX_N], d[MAX_N], visited[MAX_N];
vector<pair<int, int> > adj[MAX_N];
stack<edge> st;
void readInput() {
  cin >> n >> m;
  for (int i = 1; i <= m; ++i) {
    int u, v, w;
    cin >> u >> v >> w;
    g[u].push_back(edge(u, v, w));
    g[v].push_back(edge(v, u, w));
  }
}
void visit(int u, int par) {
  num[u] = ++timer;
  low[u] = INF;
  for (auto e : g[u]) {
    if (e.v == par) continue;
    if (num[e.v]) {
      if (num[e.v] < num[u]) st.push(e);
      low[u] = min(low[u], num[e.v]);
    } else {
      st.push(e);
      visit(e.v, u);
      low[u] = min(low[u], low[e.v]);
      if (low[e.v] >= num[u]) {
        ++nBCC;
        while (true) {
          edge tmp = st.top();
          st.pop();
          color[nBCC].push_back(tmp.w);
          if (tmp == e) break;
        }
      }
    }
  }
}
void addEdge(int u, int v, int capacity) {
  adj[u].push_back({v, nEdge});
  c[nEdge++] = capacity;
  adj[v].push_back({u, nEdge++});
}
void buildNetwork() {
  source = 0;
  target = nBCC + m + 1;
  for (int i = 1; i <= nBCC; ++i) {
    for (auto v : color[i]) addEdge(i, nBCC + v, 1);
    addEdge(source, i, max(1, (int)color[i].size() - 1));
  }
  for (int i = 1; i <= m; ++i) addEdge(i + nBCC, target, 1);
}
bool bfs() {
  for (int i = source; i <= target; ++i) d[i] = -1;
  d[source] = 0;
  queue<int> qu;
  qu.push(source);
  while (qu.size()) {
    int u = qu.front();
    qu.pop();
    if (u == target) return true;
    for (int i = 0; i < adj[u].size(); ++i) {
      int v = adj[u][i].first, idx = adj[u][i].second;
      if (c[idx] > f[idx] && d[v] == -1) {
        d[v] = d[u] + 1;
        qu.push(v);
      }
    }
  }
  return false;
}
int enlarge(int u, int delta) {
  if (u == target) return delta;
  if (visited[u] == timer) return 0;
  visited[u] = timer;
  for (int i = 0; i < adj[u].size(); ++i) {
    int v = adj[u][i].first, idx = adj[u][i].second;
    if (c[idx] > f[idx] && d[v] == d[u] + 1) {
      int x = enlarge(v, min(delta, c[idx] - f[idx]));
      if (x) {
        f[idx] += x;
        f[idx ^ 1] -= x;
        return x;
      }
    }
  }
  return 0;
}
void maxFlow() {
  int res = 0;
  while (bfs()) {
    while (true) {
      ++timer;
      int x = enlarge(source, INF);
      if (!x) break;
      res += x;
    }
  }
  cout << res;
}
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  readInput();
  visit(1, 0);
  buildNetwork();
  maxFlow();
}
