题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4424
题意:给你n个点,n-1条边,每条边有一个最大容量 c,现在规定i-j的路的最大负载量为i到j所经过的所有边的最小值,要你找一个中心点,使它到其他 n-1 个点的最大容量的和最大,然后输出这个最大值。
思路:模拟kruskal算法的实现过程,先将边进行降序排列,这样每次选择的边就是生成树中的最小瓶颈路了,这样每次在这条边所连接的A,B集合中对比总容量并选择某点成为中心
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 200010;
int num[N];
int fa[N];
long long sum[N];
struct edge
{
int a, b, w;
edge() {}
edge(int a, int b, int w) : a(a), b(b), w(w) {}
bool operator < (const edge &rhs) const
{
return w > rhs.w;
if(a != rhs.a)
return a < rhs.a;
if(b != rhs.b)
return b < rhs.b;
}
} e[N];
void init()
{
for(int i = 0; i <= N; i++)
{
fa[i] = i;
num[i] = 1;
}
memset(sum, 0, sizeof(sum));
}
int Find(int x)
{
if(x == fa[x])
return x;
return fa[x] = Find(fa[x]);
}
int main()
{
int n;
while(~scanf("%d", &n))
{
init();
for(int i = 0; i < n - 1; i++)
{
int a, b, w;
scanf("%d%d%d", &a, &b, &w);
e[i] = edge(a, b, w);
}
sort(e, e + n - 1);
for(int i = 0; i < n - 1; i++)
{
int fx = Find(e[i].a);
int fy = Find(e[i].b);
if(fx == fy) continue;
long long sx = (long long)e[i].w * num[fy] + sum[fx]; //X集合选点
long long sy = (long long)e[i].w * num[fx] + sum[fy]; //Y集合选点
if(sx > sy)
{
fa[fy] = fx;
num[fx] += num[fy];
sum[fx] = sx;
}
else
{
fa[fx] = fy;
num[fy] += num[fx];
sum[fy] = sy;
}
}
long long ans = sum[Find(1)];
cout << ans << endl;
}
return 0;
}