先对边进行从大到小的排序
并查集保存节点数和长度
4 1 2 2 2 4 1 2 3 1 4 1 2 1 2 4 1 2 3 1
4 3
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <limits.h>
#include <ctype.h>
#include <string.h>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <deque>
#include <vector>
#include <set>
#include <map>
using namespace std;
#define MAXN 200000 + 200
typedef __int64 LL;
struct node{
LL x;
LL y;
LL cost;
}E[MAXN];
LL f[MAXN];//父亲节点
LL dis[MAXN];//与该节点相连所有的点到该节点的权值的和
LL sum[MAXN];//该节点的儿子数
bool cmp(node a,node b){
return a.cost > b.cost;
}
LL find(LL x){
if(x == f[x]){
return x;
}
return f[x] = find(f[x]);
}
void init(){
LL i;
for(i=0;i<MAXN;i++){
f[i] = i;
dis[i] = 0;
sum[i] = 1;
}
}
void unio(LL x,LL y,LL v){
f[x] = y;
sum[y]+=sum[x];
dis[y] = v;
}
int main(){
LL n,i;
while(~scanf("%I64d",&n)){
for(i=1;i<n;i++){
scanf("%I64d%I64d%I64d",&E[i].x,&E[i].y,&E[i].cost);
}
sort(E+1,E+n,cmp);
init();
for(i=1;i<n;i++){
LL dx = find(E[i].x);
LL dy = find(E[i].y);
LL dis1 = dis[dx]+E[i].cost*sum[dy];//因为E【i】.cost一定要比这两个集合中的任何一条边都要短
LL dis2 = dis[dy]+E[i].cost*sum[dx];
if(dis1 > dis2){
unio(dy,dx,dis1);
}
else{
unio(dx,dy,dis2);
}
}
printf("%I64d\n",dis[find(1)]);
}
return 0;
}
原文地址:http://blog.csdn.net/zcr_7/article/details/40985565