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 MAXN = 100010, inf = 1000000, MAX = 500000;
namespace Dinic {
const int MAXV = MAX;
const int MAXE = MAX * 10;
const long long int oo = 1e18;
int V, E;
int last[MAXV], dist[MAXV], curr[MAXV];
int next[MAXE], adj[MAXE];
long long int cap[MAXE];
void init(int n) {
  V = n;
  E = 0;
  for (int i = 0; i < V; i++) last[i] = -1;
}
void edge(int x, int y, long long int c1, long long int c2) {
  adj[E] = y;
  cap[E] = c1;
  next[E] = last[x];
  last[x] = E++;
  adj[E] = x;
  cap[E] = c2;
  next[E] = last[y];
  last[y] = E++;
}
long long int push(int x, int sink, long long int flow) {
  if (x == sink) return flow;
  for (int &e = curr[x]; e != -1; e = next[e]) {
    int y = adj[e];
    if (cap[e] && dist[x] + 1 == dist[y])
      if (long long int f = push(y, sink, min(flow, cap[e])))
        return cap[e] -= f, cap[e ^ 1] += f, f;
  }
  return 0;
}
long long int run(int src, int sink) {
  long long int ret = 0;
  for (;;) {
    for (int i = 0; i < V; i++) curr[i] = last[i];
    for (int i = 0; i < V; i++) dist[i] = -1;
    queue<int> Q;
    Q.push(src), dist[src] = 0;
    while (!Q.empty()) {
      int x = Q.front();
      Q.pop();
      for (int e = last[x]; e != -1; e = next[e]) {
        int y = adj[e];
        if (cap[e] && dist[y] == -1) Q.push(y), dist[y] = dist[x] + 1;
      }
    }
    if (dist[sink] == -1) break;
    while (long long int f = push(src, sink, oo)) ret += f;
  }
  return ret;
}
}  // namespace Dinic
struct brid {
  int x, c, br;
  brid(int _x = 0, int _c = 0, int _br = 0) {
    x = _x;
    c = _c;
    br = _br;
  }
};
int n, m, num;
int cvor_bio[MAXN], brid_bio[MAXN];
vector<brid> graf[MAXN];
vector<brid> bridovi;
vector<int> grupe[MAXN];
void dfs_tree(int cvor, int prije) {
  if (cvor_bio[cvor]) {
    grupe[num].push_back(bridovi.back().c);
    for (int i = (int)bridovi.size() - 2; i >= 0; i--) {
      if (bridovi[i].x == cvor) break;
      grupe[num].push_back(bridovi[i].c);
    }
    num++;
    return;
  }
  cvor_bio[cvor] = 1;
  for (int i = 0; i < (int)graf[cvor].size(); i++) {
    int kamo = graf[cvor][i].x;
    if (kamo == prije) continue;
    if (brid_bio[graf[cvor][i].br]) continue;
    brid_bio[graf[cvor][i].br] = 1;
    bridovi.push_back(graf[cvor][i]);
    dfs_tree(kamo, cvor);
    bridovi.pop_back();
  }
}
int broj_mostova, boja[MAXN];
void debug() {
  cout << "num"
       << " = " << num << endl;
  ;
  for (int i = 0; i < num; i++) {
    for (int j = 0; j < (int)grupe[i].size(); j++) cout << grupe[i][j] << " ";
    cout << endl;
  }
}
int source, sink;
map<int, int> mat[3 * MAXN];
vector<int> flow_graf[3 * MAXN];
void dodaj_brid(int a, int b, int c) { Dinic::edge(a, b, c, 0); }
void izgradi_flow() {
  source = 0, sink = 3 * MAXN - 1;
  int brojac = 0;
  for (int i = 0; i < num; i++) {
    dodaj_brid(source, i + 1, (int)grupe[i].size() - 1);
    for (int j = 0; j < (int)grupe[i].size(); j++) {
      dodaj_brid(i + 1, MAXN + brojac, 1);
      dodaj_brid(MAXN + brojac, 2 * MAXN + grupe[i][j], 1);
      brojac++;
    }
  }
  for (int i = 1; i <= m; i++) {
    if (boja[i]) {
      broj_mostova++;
      continue;
    }
    dodaj_brid(2 * MAXN + i, sink, 1);
  }
}
int iza[3 * MAXN];
int bio[3 * MAXN], cookie;
int bfs() {
  cookie++;
  queue<int> q;
  bio[source] = cookie;
  q.push(source);
  while (!q.empty()) {
    int x = q.front();
    q.pop();
    if (x == sink) return 1;
    for (int i = 0; i < (int)flow_graf[x].size(); i++) {
      int kamo = flow_graf[x][i];
      if (bio[kamo] == cookie) continue;
      if (mat[x][kamo] == 0) continue;
      bio[kamo] = cookie;
      iza[kamo] = x;
      q.push(kamo);
    }
  }
  return 0;
}
int flow() {
  int ret = 0;
  while (bfs()) {
    int mini = inf;
    int sad = sink;
    while (sad != source) {
      int kamo = sad;
      sad = iza[sad];
      mini = min(mini, mat[sad][kamo]);
    }
    sad = sink;
    while (sad != source) {
      int kamo = sad;
      sad = iza[sad];
      mat[sad][kamo] -= mini;
      mat[kamo][sad] += mini;
    }
    ret += mini;
  }
  return ret;
}
int disc[MAXN], low_link[MAXN], timer = 1;
void dfs_mostovi(int cvor, int prije) {
  if (disc[cvor]) return;
  disc[cvor] = timer;
  low_link[cvor] = timer++;
  for (int i = 0; i < (int)graf[cvor].size(); i++) {
    int kamo = graf[cvor][i].x;
    if (kamo == prije) continue;
    dfs_mostovi(kamo, cvor);
    int t = low_link[kamo];
    if (t > disc[cvor]) boja[graf[cvor][i].c] = 1;
    low_link[cvor] = min(low_link[cvor], t);
  }
}
int main() {
  scanf("%d %d", &n, &m);
  for (int i = 0; i < m; i++) {
    int a, b, c;
    scanf("%d %d %d", &a, &b, &c);
    graf[a].push_back(brid(b, c, i));
    graf[b].push_back(brid(a, c, i));
  }
  bridovi.push_back(brid(1, 0, 0));
  dfs_tree(1, -1);
  dfs_mostovi(1, -1);
  Dinic::init(MAX);
  izgradi_flow();
  long long int rj = Dinic::run(source, sink);
  rj += broj_mostova;
  cout << rj << endl;
  return 0;
}
