[ZPG TEST 116] 最小边权和【生成树相关】
先将输入的边从小到大排序,对于一条边,它一定连接着两个联通块u与v,那么这条变对于答案的贡献是siz[u] * siz[v] * (边权 + 1) - 1,别问为什么这太显然了,一想就懂。。。
#include <cstdio> #include <algorithm> #include <cstring> const int maxn = 20005; int T, n, fa[maxn], fu, fv, siz[maxn]; long long ans; struct Edge { int u, v, w; } a[maxn]; bool cmp(const Edge & aa, const Edge & ss) { return aa.w < ss.w; } int getfa(int aa) { return fa[aa] == aa? aa: fa[aa] = getfa(fa[aa]); } int main(void) { freopen("tree.in", "r", stdin); freopen("tree.out", "w", stdout); scanf("%d", &T); while (T--) { memset(a, 0, sizeof a); ans = 0; scanf("%d", &n); for (int i = 1; i < n; ++i) { fa[i] = i; siz[i] = 1; scanf("%d%d%d", &a[i].u, &a[i].v, &a[i].w); } fa[n] = n; siz[n] = 1; std::sort(a + 1, a + n, cmp); for (int i = 1; i < n; ++i) { fu = getfa(a[i].u); fv = getfa(a[i].v); ans += (long long)siz[fu] * (long long)siz[fv] * (long long)(a[i].w + 1) - 1; fa[fu] = fv; siz[fv] += siz[fu]; } printf("%I64d\n", ans); } return 0; }