/* 题意,删除边使得图在进行最小生成树时,最小生成树唯一 当多个边的权值相同且多条边分别相连的两个点集(树)相同,则认为两条边等价,只保留其中一条 考虑到权值大小连续,从第i条边向后遍历,若 ff(li[i].u)==ff(li[l].u)&&ff(li[i].v)==ff(li[l].v) 或 ff(li[i].u)==ff(li[l].v)&&ff(li[i].v)==ff(li[l].u) 成立时,则说明两条边等价,答案添加边l的边权并继续向后遍历直到边权与i不同,随后再合并两个子树。 */ #include <bits/stdc++.h> #define ll long long #define pii pair<int, int> using namespace std; struct lin { int u; int v; ll val; bool used; } li[500001]; int fa[300001]; bool cmp(lin a, lin b) { return a.val < b.val; } int ff(int x) { if (fa[x] == 0) fa[x] = x; if (fa[x] == x) return x; return fa[x] = ff(fa[x]); } int main() { int n, m; scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) { int u, v, val; scanf("%d%d%d", &u, &v, &val); li[i].u = u; li[i].v = v; li[i].val = val; } sort(li + 1, li + 1 + m, cmp); ll ans = 0; int cnt = 0; set<ll> st; for (int i = 1; i <= m; i++) { int u = li[i].u; int v = li[i].v; ll val = li[i].val; if (ff(u)==ff(v)){ continue; } int l = i + 1; while(li[l].val==li[i].val){ if(((ff(li[l].u)==ff(u)&&ff(li[l].v)==ff(v))||(ff(li[l].v)==ff(u)&&ff(li[l].u)==ff(v)))){ ans += li[l].val; } l++; } st.insert(val); li[i].used = 1; fa[ff(v)] = ff(u); cnt++; } printf("%lld", ans); } //https://ac.nowcoder.com/acm/contest/26077/1009