#include #include #include #include #include #include using namespace std; template class y_combinator_result { Fun fun_; public: template explicit y_combinator_result(T &&fun): fun_(std::forward(fun)) {} template decltype(auto) operator()(Args &&...args) { return fun_(std::ref(*this), std::forward(args)...); } }; template decltype(auto) y_combinator(Fun &&fun) { return y_combinator_result>(std::forward(fun)); } struct disjoint_set { vector p; disjoint_set(int n) { p.assign(n, -1); } int find(int x) { if (p[x] < 0) return x; return p[x] = find(p[x]); } bool merge(int x, int y) { x = find(x); y = find(y); if(x == y) return false; p[x] = y; return true; } }; int main() { int n, m; cin >> n >> m; vector> edges; // vector>> mst(n); for(int i = 1; i <= m; i++) { int a, b, w; cin >> a >> b >> w; edges.push_back({w, i, --a, --b}); if(i <= n-1) { mst[a].push_back({b, i}); mst[b].push_back({a, i}); } } sort(edges.begin(), edges.end()); vector isintree(m+1); vector shouldbeintree(m+1); for(int i = 1; i <= n-1; i++) isintree[i] = true; disjoint_set dsu(n); for(auto [_, idx, u, v]: edges) if(dsu.merge(u, v)) shouldbeintree[idx] = true; int idx = 0; vector> ret; while(isintree != shouldbeintree) { assert(idx < edges.size()); int trueidx = edges[idx][1]; if(shouldbeintree[trueidx] && !isintree[trueidx]) { vector path; int src = edges[idx][2]; int dst = edges[idx][3]; auto dfs = y_combinator([&](auto self, int curr, int par) -> bool { if(curr == dst) return true; for(auto [nv, nidx]: mst[curr]) { if(nv == par) continue; path.push_back(nidx); if(self(nv, curr)) return true; path.pop_back(); } return false; }); assert(dfs(src, -1)); int badidx = -1; for(int out: path) { assert(isintree[out]); if(!shouldbeintree[out]) { badidx = out; break; } } assert(badidx >= 0); ret.push_back({badidx, trueidx}); mst[src].push_back({dst, trueidx}); mst[dst].push_back({src, trueidx}); for(int i = 0; i < n; i++) { for(int j = 0; j < mst[i].size(); j++) if(mst[i][j][1] == badidx) mst[i].erase(mst[i].begin() + j); } isintree[badidx] = false; isintree[trueidx] = true; } idx++; } cout << ret.size() << "\n"; for(auto [a, b]: ret) cout << a << " " << b << "\n"; }