#include <bits/stdc++.h>
using namespace std;
inline long long in() {
  int32_t x;
  scanf("%d", &x);
  return x;
}
inline long long lin() {
  long long x;
  scanf("%lld", &x);
  return x;
}
inline string get() {
  char ch[2000010];
  scanf("%s", ch);
  return ch;
}
inline void read(long long *a, long long n) {
  for (long long i = 0; i < n; i++) a[i] = in();
}
const long long maxn = 1e6 + 10;
const long long maxm = 1e6 + 10;
const long long maxlg = 21;
const long long base = 29;
const long long mod = 1e9 + 7;
const long long INF = 1e18 + 10;
stack<long long> st;
long long h[maxn], l[maxn], cnt = 2;
long long source = 0, sink = 1;
bool mark[maxn], mark2[maxn];
struct edge {
  long long v, u, flow, cap;
  edge() {}
  edge(long long v, long long u, long long flow, long long cap)
      : v(v), u(u), flow(flow), cap(cap) {}
} e[maxm];
vector<pair<long long, long long> > graph[maxn];
long long cur = 0;
vector<long long> g[maxn];
inline void add_edge(long long v, long long u, long long flow, long long cap) {
  g[v].push_back(cur);
  e[cur++] = {v, u, flow, cap};
  g[u].push_back(cur);
  e[cur++] = {u, v, -flow, 0};
}
vector<long long> finalColors;
vector<long long> colors[maxn];
inline void tarjan(long long node, long long fa = -1) {
  h[node] = l[node] = fa == -1 ? 0 : h[fa] + 1;
  st.push(node);
  mark[node] = true;
  for (auto u : graph[node]) {
    if (!mark[u.first]) {
      tarjan(u.first, node);
      l[node] = min(l[node], l[u.first]);
    } else
      l[node] = min(l[node], h[u.first]);
  }
  if (h[node] - 1 == l[node]) {
    long long x;
    vector<long long> nodes;
    do {
      x = st.top();
      st.pop();
      nodes.push_back(x);
      mark2[x] = true;
    } while (x != node);
    mark2[fa] = true;
    for (auto nd : nodes) {
      for (auto u : graph[nd]) {
        if (mark2[u.first]) {
          colors[cnt].push_back(u.second);
        }
      }
    }
    for (auto nd : nodes) mark2[nd] = false;
    mark2[fa] = false;
    long long curNode = cnt++;
    add_edge(source, curNode, 0, (long long)nodes.size());
  }
}
long long ptr[maxn], di[maxn], q[maxn];
inline bool bfs() {
  memset(di, 63, (cnt + (long long)finalColors.size() + 2) * sizeof di[0]);
  di[source] = 0;
  long long h = 0, t = 1;
  q[0] = source;
  while (h < t) {
    long long v = q[h++];
    for (long long i = 0; i < g[v].size(); i++) {
      long long u = e[g[v][i]].u;
      if (e[g[v][i]].flow == e[g[v][i]].cap) continue;
      long long cst = di[v] + 1;
      if (cst < di[u]) {
        di[u] = cst;
        q[t++] = u;
      }
    }
  }
  return di[sink] < INF;
}
inline long long push(long long node, long long flow) {
  if (node == sink || flow == 0) return flow;
  for (; ptr[node] < g[node].size(); ptr[node]++) {
    long long u = e[g[node][ptr[node]]].u;
    long long cap = e[g[node][ptr[node]]].cap, fl = e[g[node][ptr[node]]].flow;
    if (di[u] != di[node] + 1) continue;
    if (cap == fl) continue;
    long long pushed = push(u, min(flow, cap - fl));
    if (pushed == 0) continue;
    e[g[node][ptr[node]]].flow += pushed;
    e[g[node][ptr[node]] ^ 1].flow -= pushed;
    return pushed;
  }
  return 0;
}
inline long long max_flow() {
  long long x = 0;
  while (bfs()) {
    memset(ptr, 0, (cnt + (long long)finalColors.size() + 2) * sizeof ptr[0]);
    while (long long pushed = push(source, INF)) {
      x += pushed;
    }
  }
  return x;
}
int32_t main() {
  long long n = in(), m = in();
  for (long long i = 0; i < m; i++) {
    long long v = in(), u = in(), col = in();
    finalColors.push_back(col);
    graph[v].push_back({u, col});
    graph[u].push_back({v, col});
  }
  tarjan(1);
  sort(finalColors.begin(), finalColors.end());
  finalColors.resize(
      (long long)(unique(finalColors.begin(), finalColors.end()) -
                  finalColors.begin()));
  for (long long i = 2; i < cnt; i++) {
    for (long long j = 0; j < colors[i].size(); j++) {
      long long id = (long long)(lower_bound(finalColors.begin(),
                                             finalColors.end(), colors[i][j]) -
                                 finalColors.begin());
      add_edge(i, id + cnt, 0, 1);
    }
  }
  for (long long j = 0; j < finalColors.size(); j++)
    add_edge(j + cnt, sink, 0, 1);
  cout << max_flow();
}
