#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f, N = 1e6 + 5, M = 4e6 + 5, P = 2e5 + 5;
namespace iobuff {
const int LEN = 1000000;
char in[LEN + 5], out[LEN + 5];
char *pin = in, *pout = out, *ed = in, *eout = out + LEN;
inline char gc(void) {
  return pin == ed && (ed = (pin = in) + fread(in, 1, LEN, stdin), ed == in)
             ? EOF
             : *pin++;
}
inline void pc(char c) {
  pout == eout && (fwrite(out, 1, LEN, stdout), pout = out);
  (*pout++) = c;
}
inline void flush() { fwrite(out, 1, pout - out, stdout), pout = out; }
template <typename T>
inline void scan(T &x) {
  static int f;
  static char c;
  c = gc(), f = 1, x = 0;
  while (c < '0' || c > '9') f = (c == '-' ? -1 : 1), c = gc();
  while (c >= '0' && c <= '9') x = 10 * x + c - '0', c = gc();
  x *= f;
}
template <typename T>
inline void putint(T x, char div) {
  static char s[15];
  static int top;
  top = 0;
  x < 0 ? pc('-'), x = -x : 0;
  while (x) s[top++] = x % 10, x /= 10;
  !top ? pc('0'), 0 : 0;
  while (top--) pc(s[top] + '0');
  pc(div);
}
}  // namespace iobuff
using namespace iobuff;
namespace Flow {
int tot = 1, S, T, nn, fi[N], ne[M], to[M], c[M], dis[N];
inline void add(int x, int y, int s) {
  ne[++tot] = fi[x], fi[x] = tot, to[tot] = y, c[tot] = s;
  ne[++tot] = fi[y], fi[y] = tot, to[tot] = x, c[tot] = 0;
}
inline bool bfs() {
  fill(dis + 1, dis + nn + 1, -1);
  dis[S] = 0;
  queue<int> q;
  q.push(S);
  while (!q.empty()) {
    int u = q.front();
    q.pop();
    for (int i = fi[u]; i; i = ne[i]) {
      int v = to[i];
      if (c[i] && dis[v] == -1) dis[v] = dis[u] + 1, q.push(v);
    }
  }
  return dis[T] != -1;
}
int dfs(int u, int flow) {
  if (u == T || !flow) return flow;
  int used = 0;
  for (int i = fi[u]; i; i = ne[i]) {
    int v = to[i];
    if (!c[i] || dis[v] != dis[u] + 1) continue;
    int t = dfs(v, min(c[i], flow - used));
    c[i] -= t, c[i ^ 1] += t;
    used += t;
    if (flow == used) break;
  }
  if (flow > used) dis[u] = -1;
  return used;
}
inline int dinic() {
  int e = 0;
  while (bfs()) e += dfs(S, inf);
  return e;
}
}  // namespace Flow
int n, m, sum, tot = 1, fi[P], ne[P << 2], to[P << 2], c[P << 2], fa[P], dep[P],
               id[P << 2];
int tmp[P << 2], deg[P << 2], cnt;
vector<int> p[P << 2];
bool flag[P << 2];
inline void add(int x, int y, int cc) {
  ne[++tot] = fi[x], fi[x] = tot, to[tot] = y, c[tot] = cc;
}
inline int lsh() {
  cnt = 0;
  for (int i = 2; i <= tot; ++i) tmp[++cnt] = c[i];
  sort(tmp + 1, tmp + cnt + 1);
  cnt = unique(tmp + 1, tmp + cnt + 1) - tmp - 1;
  for (int i = 2; i <= tot; ++i)
    c[i] = lower_bound(tmp + 1, tmp + cnt + 1, c[i]) - tmp;
  return cnt;
}
void dfs1(int u, int f) {
  dep[u] = dep[f] + 1;
  for (int i = fi[u], v = to[i]; i; i = ne[i], v = to[i])
    if (v ^ f) {
      if (dep[v]) {
        if (dep[v] > dep[u]) continue;
        int now = u;
        ++sum;
        while (now != v) {
          id[fa[now]] = id[fa[now] ^ 1] = sum;
          now = to[fa[now]];
        }
        id[i] = id[i ^ 1] = sum;
      } else
        fa[v] = i ^ 1, dfs1(v, u);
    }
}
int main() {
  scan(n), scan(m);
  for (int i = 1, x, y, c; i <= m; ++i)
    scan(x), scan(y), scan(c), add(x, y, c), add(y, x, c);
  Flow::S = 1, Flow::T = 2;
  Flow::nn = lsh() + 2;
  for (int i = 1; i <= n; ++i)
    if (!dep[i]) dfs1(i, 0);
  for (int i = 2; i <= tot; i += 2)
    if (!id[i])
      flag[c[i]] = 1;
    else
      p[id[i]].push_back(i);
  int ss = 0;
  for (int i = 1; i <= sum; ++i) {
    int np = ++Flow::nn;
    Flow::add(Flow::S, np, 1), ++ss;
    for (int t : p[i]) Flow::add(np, c[t] + 2, 1), ++deg[c[t]];
  }
  for (int i = 1; i <= cnt; ++i) {
    if (!flag[i]) {
      if (deg[i] > 1) Flow::add(i + 2, Flow::T, deg[i] - 1);
    } else
      Flow::add(i + 2, Flow::T, deg[i]);
  }
  printf("%d\n", cnt - (ss - Flow::dinic()));
  return 0;
}
