#include <bits/stdc++.h>
using namespace std;
vector<int> v[100100];
int v1[100100];
int v2[100100];
int color[100100];
bool in_cycle[100100];
int getnext(int s, int eid) {
  if (v1[eid] == s)
    return v2[eid];
  else
    return v1[eid];
}
vector<vector<int> > cycles;
int stcnt = 0;
int st[100100];
int vis[100100];
map<pair<int, int>, int> wtf;
vector<int> getedges(vector<int> cycle) {
  vector<int> res;
  for (int i = 0; i < (int)(cycle).size(); i++) {
    int cur = cycle[i];
    int nxt = cycle[(i + 1) % (int)(cycle).size()];
    res.push_back(wtf[make_pair(cur, nxt)]);
  }
  return res;
}
void go(int s, int lst = -1) {
  if (vis[s] == 2) {
    vector<int> cycle;
    for (int i = stcnt - 1; i >= 0; i--) {
      cycle.push_back(st[i]);
      if (st[i] == s) break;
    }
    cycles.push_back(getedges(cycle));
    return;
  }
  if (vis[s] == 1) return;
  st[stcnt++] = s;
  vis[s] = 2;
  for (int i = 0; i < (int)(v[s]).size(); i++) {
    int eid = v[s][i];
    int nxt = getnext(s, eid);
    if (nxt == lst) continue;
    go(nxt, s);
  }
  vis[s] = 1;
  stcnt--;
}
int good_color[100100];
vector<int> who_cycles[100100];
bool bad_cycle[100100];
void make_bad_cycle(int cyc);
void make_good_color(int col);
void make_bad_cycle(int cyc) {
  if (bad_cycle[cyc]) return;
  bad_cycle[cyc] = true;
  for (int i = 0; i < (int)(cycles[cyc]).size(); i++) {
    int eid = cycles[cyc][i];
    int col = color[eid];
    make_good_color(col);
  }
}
void make_good_color(int col) {
  if (good_color[col]) return;
  good_color[col] = true;
  for (int i = 0; i < (int)(who_cycles[col]).size(); i++) {
    make_bad_cycle(who_cycles[col][i]);
  }
}
vector<int> graph[100100];
int F[100100];
int C[100100];
int frfr[100100];
int toto[100100];
bool VIS[100100];
vector<int> VISITED;
bool dfs(int s, int T) {
  if (s == T) return true;
  if (VIS[s]) return false;
  VIS[s] = true;
  VISITED.push_back(s);
  for (int i = 0; i < (int)(graph[s]).size(); i++) {
    int nxt = toto[graph[s][i]];
    int fff = F[graph[s][i]];
    int ccc = C[graph[s][i]];
    if (ccc - fff > 0 && dfs(nxt, T)) {
      F[graph[s][i]]++;
      F[graph[s][i] ^ 1]--;
      return true;
    }
  }
  return false;
}
int solve(int S, int T) {
  int res = 0;
  while (dfs(S, T)) {
    while (!VISITED.empty()) {
      VIS[VISITED.back()] = false;
      VISITED.pop_back();
    }
    res++;
  }
  return res;
}
void add_edge(int FROM, int TO, int eid, int c) {
  graph[FROM].push_back(eid);
  graph[TO].push_back(eid ^ 1);
  frfr[eid] = FROM;
  toto[eid] = TO;
  frfr[eid ^ 1] = TO;
  toto[eid ^ 1] = FROM;
  C[eid] = c;
  C[eid ^ 1] = 0;
  F[eid] = 0;
  F[eid ^ 1] = 0;
}
int main() {
  int n, m;
  scanf("%d %d", &n, &m);
  for (int i = 1; i <= m; i++) {
    int a, b, c;
    scanf("%d %d %d", &a, &b, &c);
    v1[i] = a;
    v2[i] = b;
    color[i] = c;
    v[a].push_back(i);
    v[b].push_back(i);
    wtf[make_pair(a, b)] = i;
    wtf[make_pair(b, a)] = i;
  }
  go(1);
  for (int i = 0; i < (int)(cycles).size(); i++) {
    for (int j = 0; j < (int)(cycles[i]).size(); j++) {
      int eid = cycles[i][j];
      int col = color[eid];
      in_cycle[eid] = true;
      who_cycles[col].push_back(i);
    }
  }
  for (int i = 1; i <= m; i++) {
    if (!in_cycle[i]) {
      make_good_color(color[i]);
    }
  }
  for (int i = 1; i <= m; i++) {
    sort(who_cycles[i].begin(), who_cycles[i].end());
    for (int j = 1; j < (int)(who_cycles[i]).size(); j++) {
      if (who_cycles[i][j] == who_cycles[i][j - 1]) {
        make_bad_cycle(who_cycles[i][j]);
      }
    }
  }
  int res = 0;
  int S = 0;
  vector<vector<int> > good_cycles;
  for (int i = 0; i < (int)(cycles).size(); i++) {
    if (!bad_cycle[i]) {
      vector<int> tmp;
      for (int j = 0; j < (int)(cycles[i]).size(); j++) {
        tmp.push_back(color[cycles[i][j]]);
      }
      good_cycles.push_back(tmp);
    }
  }
  int CUREID = 0;
  if ((int)(good_cycles).size() != 0) {
    int CUR = 1;
    int CYC_BEGIN = CUR;
    for (int i = 0; i < (int)(good_cycles).size(); i++) {
      add_edge(S, CUR, CUREID, (int)(good_cycles[i]).size() - 1);
      CUREID += 2;
      CUR++;
    }
    int CYC_END = CUR - 1;
    int COL_BEGIN = CUR;
    int COL_END = CUR + m - 1;
    for (int i = 0; i < (int)(good_cycles).size(); i++) {
      for (int j = 0; j < (int)(good_cycles[i]).size(); j++) {
        int col = good_cycles[i][j];
        int FROM = i + 1;
        int TO = COL_BEGIN + col - 1;
        add_edge(FROM, TO, CUREID, 1);
        CUREID += 2;
      }
    }
    int T = COL_END + 1;
    for (int i = COL_BEGIN; i <= COL_END; i++) {
      int FROM = i;
      int TO = T;
      add_edge(FROM, TO, CUREID, 1);
      CUREID += 2;
    }
    res += solve(S, T);
  }
  for (int i = 1; i <= m; i++) {
    if (good_color[i]) {
      res++;
    }
  }
  printf("%d\n", res);
  return 0;
}
