題意:給出n個點和n-1條邊,a到b的最大承載量為a和b之間承載量的最小值。以某一點為中心,求承載量之和的最大值。
由於a和b之間的承載量為它們之間承載量的最小值,所以先以兩點之間的承載量從大到小排序。每次合並時有A,B兩個集合,他們之間的承載量(cost)為當前最小,如果B合並到A,則A的總承載量為A之前的總承載量加上A,B之間的承載量成衣集合B中點的個數,即 cost[A]=cost[A]+num[B]*cost.
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int inf=1000000000;
const int maxn=200005;
int f[maxn];
ll num[maxn],cost[maxn];
struct Branch
{
int a;
int b;
ll cost;
}bra[maxn];
bool cmp(Branch a,Branch b)
{
return a.cost>b.cost;
}
int Find(int x)
{
if(x!=f[x])
f[x]=Find(f[x]);
return f[x];
}
ll Function(int n)
{
for(int i=0;i<n-1;i++)
{
int a=Find(bra[i].a);
int b=Find(bra[i].b);
if(cost[a]+num[b]*bra[i].cost>=cost[b]+num[a]*bra[i].cost)
{
f[b]=a;
cost[a]+=num[b]*bra[i].cost;
num[a]+=num[b];
}
else
{
f[a]=b;
cost[b]+=num[a]*bra[i].cost;
num[b]+=num[a];
}
}
return cost[Find(1)];
}
int main()
{
//freopen("in.txt","r",stdin);
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i=0;i<=n;i++)
{
f[i]=i;
num[i]=1;
}
memset(cost,0,sizeof(cost));
for(int i=0;i<n-1;i++)
scanf("%d%d%I64d",&bra[i].a,&bra[i].b,&bra[i].cost);
sort(bra,bra+n-1,cmp);
printf("%I64d\n",Function(n));
}
return 0;
}