Tree is a connected undirected graph that has no cycles. Edge cactus is a connected undirected graph without loops and parallel edges, such that each edge belongs to at most one cycle.

Vasya has an edge cactus, each edge of this graph has some color.

Vasya would like to remove the minimal number of edges in such way that his cactus turned to a tree. Vasya wants to make it in such a way that there were edges of as many different colors in the resulting tree, as possible. Help him to find how many different colors can the resulting tree have.

Input

The first line contains two integers: n, m (2 ≤ n ≤ 10 000) — the number of vertices and the number of edges in Vasya's graph, respectively.

The following m lines contain three integers each: u, v, c (1 ≤ u, v ≤ n, u ≠ v, 1 ≤ c ≤ m) — the numbers of vertices connected by the corresponding edge, and its color. It is guaranteed that the described graph is indeed an edge cactus.

Output

Output one integer: the maximal number of different colors that the resulting tree can have.

Examples

Input

4 4
1 2 4
2 3 1
3 4 2
4 2 3


Output

3


Input

7 9
1 2 1
2 3 4
3 1 5
1 4 5
4 5 2
5 1 6
1 6 4
6 7 6
7 1 3


Output

6
#include <bits/stdc++.h>
using namespace std;
const int MOD = (int)1e9 + 7;
const int INF = (int)1e9;
const long long LINF = (long long)1e18;
const long double PI = acos((long double)-1);
const long double EPS = 1e-9;
inline long long gcd(long long a, long long b) {
  long long r;
  while (b) {
    r = a % b;
    a = b;
    b = r;
  }
  return a;
}
inline long long lcm(long long a, long long b) { return a / gcd(a, b) * b; }
inline long long fpow(long long n, long long k, int p = MOD) {
  long long r = 1;
  for (; k; k >>= 1) {
    if (k & 1) r = r * n % p;
    n = n * n % p;
  }
  return r;
}
template <class T>
inline int chkmin(T& a, const T& val) {
  return val < a ? a = val, 1 : 0;
}
template <class T>
inline int chkmax(T& a, const T& val) {
  return a < val ? a = val, 1 : 0;
}
inline long long isqrt(long long k) {
  long long r = sqrt(k) + 1;
  while (r * r > k) r--;
  return r;
}
inline long long icbrt(long long k) {
  long long r = cbrt(k) + 1;
  while (r * r * r > k) r--;
  return r;
}
inline void addmod(int& a, int val, int p = MOD) {
  if ((a = (a + val)) >= p) a -= p;
}
inline void submod(int& a, int val, int p = MOD) {
  if ((a = (a - val)) < 0) a += p;
}
inline int mult(int a, int b, int p = MOD) { return (long long)a * b % p; }
inline int inv(int a, int p = MOD) { return fpow(a, p - 2, p); }
struct Dinic {
  static const int oo = (int)1e9;
  static const int MAXV = 100000 + 10;
  static const int MAXE = 1000000 + 10;
  int n, s, t, E, adj[MAXE], next[MAXE], last[MAXV], run[MAXV], level[MAXV],
      que[MAXV];
  int flow[MAXE], cap[MAXE];
  void init(int _n, int _s, int _t) {
    n = _n;
    s = _s;
    t = _t;
    E = 0;
    fill_n(last, n + 1, -1);
  }
  void add(int u, int v, int c1, int c2) {
    adj[E] = v;
    flow[E] = 0;
    cap[E] = c1;
    next[E] = last[u];
    last[u] = E++;
    adj[E] = u;
    flow[E] = 0;
    cap[E] = c2;
    next[E] = last[v];
    last[v] = E++;
  }
  int bfs() {
    fill_n(level, n + 1, -1);
    level[s] = 0;
    int qsize = 0;
    que[qsize++] = s;
    for (int i = 0; i < qsize; i++) {
      for (int u = que[i], e = last[u]; ~e; e = next[e]) {
        int v = adj[e];
        if (flow[e] < cap[e] && !~level[v]) {
          level[v] = level[u] + 1;
          que[qsize++] = v;
        }
      }
    }
    return level[t] != -1;
  }
  int dfs(int u, int bot) {
    if (u == t) return bot;
    for (int& e = run[u]; ~e; e = next[e]) {
      int v = adj[e];
      int delta = 0;
      if (level[v] == level[u] + 1 && flow[e] < cap[e] &&
          (delta = dfs(v, min(bot, cap[e] - flow[e]))) > 0) {
        flow[e] += delta;
        flow[e ^ 1] -= delta;
        return delta;
      }
    }
    return 0;
  }
  int maxflow() {
    int total = 0;
    while (bfs()) {
      for (int i = 0; i <= n; i++) run[i] = last[i];
      for (int delta = dfs(s, oo); delta > 0; delta = dfs(s, oo))
        total += delta;
    }
    return total;
  }
} dinic;
const int maxn = 1000000 + 10;
int n, m;
vector<pair<int, int> > adj[maxn];
int w[maxn];
pair<int, int> from[maxn];
int vis[maxn];
int del[maxn];
int cnt;
void dfs(int u, int p = -1) {
  vis[u] = 1;
  for (int i = (0); i < (int((adj[u]).size())); i++) {
    int v = adj[u][i].first;
    int ix = adj[u][i].second;
    if (!vis[v]) {
      from[v] = make_pair(u, ix);
      dfs(v, u);
    } else if (v != p && !del[ix]) {
      vector<int> vv;
      vv.push_back(w[ix]);
      del[ix] = 1;
      int ptr = u;
      while (ptr != v) {
        int ix = from[ptr].second;
        vv.push_back(w[ix]);
        del[ix] = 1;
        ptr = from[ptr].first;
      }
      dinic.add(dinic.s, cnt, int((vv).size()) - 1, 0);
      for (int i = (0); i < (int((vv).size())); i++) {
        dinic.add(cnt, n + vv[i] - 1, 1, 0);
      }
      cnt++;
    }
  }
}
void solve() {
  cin >> n >> m;
  for (int i = (0); i < (m); i++) {
    int u, v;
    cin >> u >> v >> w[i];
    u--, v--;
    adj[u].push_back(make_pair(v, i)), adj[v].push_back(make_pair(u, i));
  }
  int tot = n + m, s = tot++, t = tot++;
  dinic.init(tot, s, t);
  for (int i = (0); i < (m); i++) dinic.add(n + i, t, 1, 0);
  dfs(0);
  for (int i = (0); i < (m); i++)
    if (!del[i]) {
      dinic.add(s, n + w[i] - 1, 1, 0);
    }
  cout << dinic.maxflow() << "\n";
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  solve();
  return 0;
}
