题意:给一棵树,从一个点到另一个点的费用是路径上所有边的费用的最小值。找一个点,使它到其他n-1个点的费用和最大。
要使费用最大,就要使经过权值大的边的路径尽可能多,因此按边的权值从大到小排序,判断是哪个点到哪个点的增益最大,用并查集连在一起,最后输出整个的费用就行。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 200000 + 10;
#define ll long long
int par[maxn];
int num[maxn];
ll sum[maxn];
int N;
struct Edge
{
int u, v;
ll cost;
} edge[maxn];
bool cmp(Edge a, Edge b)
{
return a.cost > b.cost;
}
void init(int n)
{
for (int i = 1; i <= n; i++)
{
par[i] = i;
num[i] = 1;
sum[i] = 0;
}
}
int find(int x)
{
if (x == par[x]) return x;
else return par[x] = find(par[x]);
}
void join(int x, int y, ll w)
{
x = find(x);
y = find(y);
if (x == y) return;
ll a = sum[x] + num[y] * w;
ll b = sum[y] + num[x] * w;
if (a > b)
{
par[y] = x;
sum[x] += num[y] * w;
num[x] += num[y];
}
else
{
par[x] = y;
sum[y] += num[x] * w;
num[y] += num[x];
}
}
int main()
{
while (scanf("%d", &N) != EOF)
{
init(N);
for (int i = 1; i <= N - 1; i++)
scanf("%d %d %lld", &edge[i].u, &edge[i].v, &edge[i].cost);
sort(edge + 1, edge + N, cmp);
for (int i = 1; i <= N - 1; i++)
join(edge[i].u, edge[i].v, edge[i].cost);
printf("%lld\n", sum[find(1)]);
}
return 0;
}