#include <bits/stdc++.h>
using namespace std;
namespace Dinic {
const int INF = 1e9 + 1e8;
const int N = 222222;
const int M = 222222;
int fst[N], nxt[M], to[M];
int cap[M];
int dis[N], q[N], ptr[N];
int V, E;
void init() {
  memset(fst, -1, sizeof fst);
  V = E = 0;
}
inline int add_node() {
  V++;
  return V - 1;
}
inline void add_edge(int u, int v, int c) {
  to[E] = v, cap[E] = c, nxt[E] = fst[u], fst[u] = E++;
  to[E] = u, cap[E] = 0, nxt[E] = fst[v], fst[v] = E++;
}
inline bool bfs(int S, int T, int n) {
  memset(dis, -1, sizeof(int) * n);
  int h = 0, t = 0;
  dis[S] = 0, q[t++] = S;
  while (h < t) {
    int u = q[h++];
    for (int e = fst[u]; ~e; e = nxt[e])
      if (cap[e] > 0 && dis[to[e]] == -1) {
        dis[to[e]] = dis[u] + 1, q[t++] = to[e];
        if (to[e] == T) return 1;
      }
  }
  return (dis[T] != -1);
}
int dfs(int u, int T, int f) {
  if (u == T) return f;
  for (int &e = ptr[u]; ~e; e = nxt[e])
    if (cap[e] > 0 && dis[to[e]] > dis[u]) {
      int ret = dfs(to[e], T, min(f, cap[e]));
      if (ret > 0) {
        cap[e] -= ret, cap[e ^ 1] += ret;
        return ret;
      }
    }
  return 0;
}
int max_flow(int S, int T, int n = V) {
  int ret = 0;
  while (bfs(S, T, n)) {
    memcpy(ptr, fst, sizeof(int) * n);
    for (int cur; (cur = dfs(S, T, INF)) > 0; ret += cur)
      ;
  }
  return ret;
}
}  // namespace Dinic
const int N = 222222;
struct Edge {
  int u, v, c;
  Edge(int u = 0, int v = 0, int c = 0) : u(u), v(v), c(c) {}
  int to(int x) {
    if (x == u) return v;
    return u;
  }
} E[N];
vector<int> con[N];
int vis[N], prv[N], idn, chk[N];
int src, sink;
void dfs(int u, int p) {
  vis[u] = 1;
  for (int e : con[u]) {
    int v = E[e].to(u);
    if (v == p) continue;
    if (!vis[v]) {
      prv[v] = e;
      dfs(v, u);
    } else if (!chk[e]) {
      idn++;
      int cnt = 0;
      for (int cur = u; cur && cur != v; cur = E[prv[cur]].to(cur)) {
        chk[prv[cur]] = 1;
        Dinic::add_edge(E[prv[cur]].c, idn, 1);
        cnt++;
      }
      chk[e] = 1;
      Dinic::add_edge(E[e].c, idn, 1);
      Dinic::add_edge(idn, sink, cnt);
    }
  }
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0), cout.tie(0);
  int n, m;
  cin >> n >> m;
  for (int i = 1; i <= m; i++) {
    int u, v, c;
    cin >> u >> v >> c;
    E[i] = Edge(u, v, c);
    con[u].push_back(i), con[v].push_back(i);
  }
  Dinic::init();
  idn = m;
  src = m + m + 1, sink = src + 1;
  for (int i = 1; i <= n; i++)
    if (!vis[i]) dfs(1, 0);
  for (int i = 1; i <= m; i++)
    if (!chk[i])
      Dinic::add_edge(E[i].c, ++idn, 1), Dinic::add_edge(idn, sink, 1);
  for (int i = 1; i <= m; i++) Dinic::add_edge(src, i, 1);
  cout << Dinic::max_flow(src, sink, sink + 3) << endl;
  return 0;
}
