Problem: Example

Input

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


Output

1 3

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;

#define rep(i, a, b) for (int i = a; i < (b); ++i)
#define trav(a, x) for (auto& a : x)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

int n, m;
map<int, vector<pair<int, int>>> edgelist;
int dsu[505];

int find(int n) {
	return n == dsu[n] ? n : dsu[n] = find(dsu[n]);
}

void merge(int u, int v) {
	u = find(u), v = find(v);
	if (u == v) return;
	dsu[v] = u;
}

vi num, st;
vector<vector<pii>> ed;
int Time;

template<class F>
int dfs(int at, int par, F& f) {
	int me = num[at] = ++Time, e, y, top = me;
	trav(pa, ed[at]) if (pa.second != par) {
		tie(y, e) = pa;
		if (num[y]) {
			top = min(top, num[y]);
			if (num[y] < me)
				st.push_back(e);
		} else {
			int si = sz(st);
			int up = dfs(y, e, f);
			top = min(top, up);
			if (up == me) {
				st.push_back(e);
				st.resize(si);
			}
			else if (up < me) st.push_back(e);
			else {
				//cout << "!!!!" << endl;
				f(e);
			}
		}
	}
	return top;
}

template<class F>
void bicomp(F f) {
	num.assign(sz(ed), 0);
	rep(i, 0, sz(ed)) if (!num[i]) dfs(i, -1, f);
}

int main() {
	/*
	cin.sync_with_stdio(false); cin.tie(0);
	cin.exceptions(cin.failbit);
	*/

	rep(i, 0, 505) dsu[i] = i;
	
	cin >> n >> m;
	rep(i, 0, m) {
		int s, d, c; cin >> s >> d >> c;
		//cout << s << " " << d << " " << c << endl;
		edgelist[c].push_back({s, d});
	}

	int nab = 0, sumnab = 0;

	for (auto p : edgelist) {
		//cout << "!!" << endl;
		//cout << p.first << " / " << p.second.size() << endl;
		vector<pair<int, int>> edges = p.second;
		int eid = 0;
		
		vector<int> dirty;
		vector<pair<int, int>> chosen;

		ed.clear(); ed.resize(505);

		//cout << edges.size() << endl;
		for (auto edge : edges) {
			///cout << "!!!" << edge.first << " " << edge.second << endl;
			int u, v; tie(u, v) = edge;
			//printf("%d <-> %d\n", u, v);
			u = find(u), v = find(v);
			//printf("Equiv %d <-> %d\n", u, v);
			if (u != v) {
				dirty.push_back(u), dirty.push_back(v);
				ed[u].emplace_back(v, eid);
				ed[v].emplace_back(u, eid++);
				chosen.emplace_back(u, v);
				//printf("Edge: (%d, %d)\n", u, v);
			}
			//printf("Edge %d is %d, %d\n", eid-1, chosen[eid-1].first, chosen[eid-1].second);
		}
		
		bicomp([&] (const int edge_id) {
			nab++, sumnab += p.first;
				});

		for (auto edge : edges) merge(edge.first, edge.second);

		for (int h : dirty) ed[h].clear();
	}
	cout << nab << " " << sumnab << endl;
}