[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;
}
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号