[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;
}

  

posted @ 2016-11-15 20:29  ciao_sora  阅读(308)  评论(0编辑  收藏  举报