#include <bits/stdc++.h>
using namespace std;
struct network_flow {
  struct edge {
    int flow, t, next;
  } e[(50005) * 2];
  int cnt, head[(30005)];
  void addedge(int f, int t, int flow) {
    e[++cnt] = (edge){flow, t, head[f]};
    head[f] = cnt;
    e[++cnt] = (edge){0, f, head[t]};
    head[t] = cnt;
  }
  int S, T;
  int dis[(30005)], cur[(30005)];
  bool BFS() {
    memset(dis, 0x3f, sizeof(dis));
    dis[S] = 0;
    queue<int> que;
    que.push(S);
    while (!que.empty()) {
      int u = que.front();
      que.pop();
      for (int i = head[u]; i; i = e[i].next) {
        if (e[i].flow != 0 && dis[e[i].t] == 0x3f3f3f3f) {
          dis[e[i].t] = dis[u] + 1;
          que.push(e[i].t);
        }
      }
    }
    return dis[T] != 0x3f3f3f3f;
  }
  int DFS(int u, int a) {
    if (u == T || a == 0) return a;
    int ret = 0;
    for (int &i = cur[u]; i; i = e[i].next) {
      if (e[i].flow == 0 || dis[e[i].t] != dis[u] + 1) continue;
      int f = DFS(e[i].t, a < e[i].flow ? a : e[i].flow);
      if (f) {
        e[i].flow -= f;
        e[i ^ 1].flow += f;
        ret += f;
        a -= f;
        if (a == 0) return ret;
      }
    }
    return ret;
  }
  int Dinic(int S1, int T1) {
    S = S1, T = T1;
    int ret = 0;
    while (BFS()) {
      memcpy(cur, head, sizeof(head));
      ret += DFS(S1, 0x3f3f3f3f);
    }
    return ret;
  }
  network_flow() { cnt = 1; }
} din;
struct edge {
  int t, next;
} e[20005 * 2];
int ecnt = 1, head[10005];
void addedge(int f, int t) {
  e[++ecnt] = (edge){t, head[f]};
  head[f] = ecnt;
  e[++ecnt] = (edge){f, head[t]};
  head[t] = ecnt;
}
int color[20005], belong[20005], ltcnt = 0, size[20005];
int sta[20005], top = 0, cl[10005], tcnt;
void DFS(int u, int fr) {
  if (cl[u] != 0) {
    belong[sta[top--] >> 1] = ++ltcnt, size[ltcnt] = 1;
    while (top && cl[e[sta[top]].t] > cl[u])
      belong[sta[top--] >> 1] = ltcnt, size[ltcnt]++;
    return;
  }
  if (cl[u] == 0) cl[u] = ++tcnt;
  for (int i = head[u]; i; i = e[i].next) {
    if (e[i].t != fr && cl[e[i].t] < cl[u]) sta[++top] = i, DFS(e[i].t, u);
  }
  if (e[sta[top]].t == u) belong[sta[top--] >> 1] = ++ltcnt, size[ltcnt] = 1;
}
int n, m;
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 1, f, t; i <= m; i++)
    scanf("%d%d%d", &f, &t, &color[i]), addedge(f, t);
  DFS(1, 0);
  int S = ltcnt + m + 1, T = S + 1;
  for (int i = 1; i <= ltcnt; i++) din.addedge(S, i, max(1, size[i] - 1));
  for (int i = 1; i <= m; i++)
    din.addedge(belong[i], color[i] + ltcnt, 1), din.addedge(i + ltcnt, T, 1);
  cout << din.Dinic(S, T) << endl;
  return 0;
}
