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, n) for(int i = 0; i < n; i++)
#define rep2(i, x, n) for(int i = x; i <= n; i++)
#define rep3(i, x, n) for(int i = x; i >= n; i--)
#define elif else if
#define sp(x) fixed << setprecision(x)
#define pb push_back
#define eb emplace_back
#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using pil = pair<int, ll>;
using pli = pair<ll, int>;
using pll = pair<ll, ll>;
const ll MOD = 1e9+7;
//const ll MOD = 998244353;
const int inf = (1<<30)-1;
const ll INF = (1LL<<60)-1;
const ld EPS = 1e-10;
template<typename T> bool chmax(T &x, const T &y) {return (x < y)? (x = y, true) : false;};
template<typename T> bool chmin(T &x, const T &y) {return (x > y)? (x = y, true) : false;};

struct Union_Find_Tree{
    vector<int> par, rank, num;
    
    Union_Find_Tree(int N){
        par.assign(N, -1);
        rank.assign(N, 0);
        num.assign(N, 1);
    }
    
    int root(int x){
        if(par[x] < 0 || par[x] == x) return x;
        return par[x] = root(par[x]);
    }
    
    bool unite(int x, int y){
        x = root(x), y = root(y);
        if(x == y) return false;
        if(rank[x] < rank[y]) swap(x, y);
        if(rank[x] == rank[y]) rank[x]++;
        par[y] = x, num[x] += num[y];
        return true;
    }
    
    int size(int x) {return num[root(x)];}
    
    bool same(int x, int y){
        return root(x) == root(y);
    }
    
    void clear(){
        fill(all(par), -1);
        fill(all(rank), 0);
        fill(all(num), 1);
    }
};

struct edge{int u, v;};

vector<int> G[500];
vector<bool> used(500, false);
int s, t;

void dfs(int now){
    used[now] = true;
    for(auto &e: G[now]){
        if(now == s && e == t) continue;
        if(used[e]) continue;
        dfs(e);
    }
}

int main(){
    int N, M;
    cin >> N >> M;
    int MAX = 10000;
    vector<edge> es[MAX+1];
    rep(i, M){
        int u, v, c;
        cin >> u >> v >> c;
        u--, v--;
        es[c].eb((edge){u, v});
    }
    vector<edge> check[MAX+1];
    Union_Find_Tree uf(N);
    rep2(i, 1, MAX){
        for(auto &e: es[i]){
            if(uf.unite(e.u, e.v)) check[i].eb(e);
        }
    }
    int cnt = 0, sum = 0;
    rep2(i, 1, MAX){
        for(auto &e: es[i]){
            G[e.u].pb(e.v), G[e.v].pb(e.u);
        }
        for(auto &e: check[i]){
            s = e.u, t = e.v;
            dfs(s);
            if(!used[t]) cnt++, sum += i;
            fill(all(used), false);
        }
    }
    cout << cnt << ' ' << sum << endl;
}