#include <bits/stdc++.h>   #pragma GCC optimize( -O3 )   using namespace std;   const long long mod = 998244353;   struct edge {     int u, v, cap;     edge() {}     edge(int _u, int _v, int _cap) : u(_u), v(_v), cap(_cap) {}     int get(int t) { return t ^ u ^ v; }   };   const int inf = 1e9;   struct edkarp {     vector<edge> edges;     vector<vector<int>> adj;     int n;     void init(int _n) {       n = _n;       adj.assign(n, vector<int>(0));     }     inline int comp(int i) { return i ^ 1; }     inline int par(int i, int ed) { return edges[ed].get(i); }     void add(int u, int v, int c) {       adj[u].emplace_back(edges.size());       edges.emplace_back(u, v, c);       adj[v].emplace_back(edges.size());       edges.emplace_back(u, v, 0);     }     int bfs(int st, int tar, vector<int> &p) {       p.assign(n, -1);       p[st] = -2;       queue<pair<int, int>> q;       q.push(make_pair(st, inf));       while (!q.empty()) {         int i = q.front().first, flow = q.front().second;         q.pop();         for (auto &x : adj[i]) {           if (p[par(i, x)] == -1 && edges[x].cap) {             p[par(i, x)] = x;             int nf = min(flow, edges[x].cap);             if (par(i, x) == tar) {               return nf;             }             q.push(make_pair(par(i, x), nf));           }         }       }       return 0;     }     int maxflow(int st, int tar) {       vector<int> p(n);       int flow = 0;       int nf;       while (nf = bfs(st, tar, p)) {         flow += nf;         int cr = tar;         while (cr != st) {           edges[p[cr]].cap -= nf;           edges[comp(p[cr])].cap += nf;           cr = par(cr, p[cr]);         }       }       return flow;     }   };   struct edgeg {     int u, v, c, lo;     bool in_loop = false;     edgeg() {}     edgeg(int _u, int _v, int _c) : u(_u), v(_v), c(_c), lo(-1) {}     int get(int t) { return t ^ u ^ v; }   };   const int N = 1e4 + 5;   int n, m, u, v, c, vis[N], p[N], vis1[N];   vector<int> adj[N];   vector<bool> avai;   vector<vector<int>> loops;   vector<edgeg> edges;   edkarp fo;   inline int geta(int x, int edge_num) { return edges[edge_num].get(x); }   void dfs(int i, int par) {     vis[i] = 1;     vis1[i] = 1;     for (int x : adj[i]) {       int u = geta(i, x);       if (u == par) continue;       if (vis[u]) {         if (!vis1[u]) continue;         edges[x].in_loop = true;         vector<int> clrs;         clrs.push_back(edges[x].c);         u = i;         while (u != geta(i, x)) {           edges[p[u]].in_loop = true;           clrs.push_back(edges[p[u]].c);           u = geta(u, p[u]);         }         sort(clrs.begin(), clrs.end());         auto it = unique(clrs.begin(), clrs.end());         if (it != clrs.end()) {           for (auto it1 = clrs.begin(); it1 != it; it1++) {             avai[*it1] = 1;           }         } else {           loops.push_back(clrs);         }       } else {         p[u] = x;         dfs(u, i);       }     }     vis1[i] = 0;   }   void solve() {     cin >> n >> m;     avai.assign(m, 0);     for (int i = 0; i < m; i++) {       cin >> u >> v >> c;       u--, v--, c--;       adj[u].push_back(edges.size());       adj[v].push_back(edges.size());       edges.emplace_back(u, v, c);     }     fill(vis, vis + n, 0);     fill(vis1, vis1 + n, 0);     dfs(0, -1);     int cr = 0;     for (int i = 0; i < (int)edges.size(); i++) {       if (!edges[i].in_loop) {         avai[edges[i].c] = 1;       }     }     fo.init((int)loops.size() + m + 2);     for (int i = 0; i < (int)loops.size(); i++) {       fo.add(0, i + 1, (int)loops[i].size() - 1);       for (int c : loops[i]) {         if (avai[c]) continue;         fo.add(i + 1, (int)loops.size() + 1 + c, 1);       }     }     int flow = 0;     for (int i = 0; i < m; i++) {       flow += avai[i];     }     for (int i = (int)loops.size() + 1; i <= (int)loops.size() + m; i++) {       fo.add(i, (int)loops.size() + m + 1, 1);     }     flow += fo.maxflow(0, (int)loops.size() + m + 1);     cout << flow <<   n ;   }   int main() {     ios_base::sync_with_stdio(false);     cin.tie(0);     cout.tie(0);     int t = 1;     while (t--) {       solve();     }   }