这道题是在CF上看到的~http://vjudge.net/contest/view.action?cid=49082#problem/C,主要是练习并查集
先说一下题意:有n个城镇,有n-1条边使得这n个城镇构成一个连通图,每条边都有一个权值。
现在的要求是:从n个城镇中选一个中心城镇,使得中心城镇到其他n-1个城镇的D值和最大,D值是城镇i 到 城镇 j route上最小权值的road..
比如 城镇3到城镇4 权值是90. 城镇4到城镇5权值是80,那么3 到5 的D值就是80.
可以用神奇的并查集解决这一问题,因为有n-1条边,所以先把边按从大到小排序,然后一个个并;
具体看代码:
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
struct Node
{
int cnt;
long long sum;
}node[200010];
struct Edge
{
int a,b,c;
}edge[200010];
int f[200010];
int cmp(Edge a,Edge b)
{
return a.c>b.c;
}
int find(int x)
{
if(f[x]!=x)
f[x]=find(f[x]);
return f[x];
}
int main()
{
int n;
while(cin>>n)
{
for(int i=1;i<=n;i++)
{
node[i].cnt=1;
node[i].sum=0;
f[i]=i;
}
for(int i=0;i<n-1;i++)
cin>>edge[i].a>>edge[i].b>>edge[i].c;
sort(edge,edge+n-1,cmp);
for(int i=0;i<n-1;i++)
{
int f1=find(edge[i].a);
int f2=find(edge[i].b);
long long temp1=node[f1].sum+(long long )edge[i].c*node[f2].cnt;
long long temp2=node[f2].sum+(long long )edge[i].c*node[f1].cnt;
if(temp1>temp2)
{
f[f2]=f1;
node[f1].sum=temp1;
node[f1].cnt+=node[f2].cnt;
}
else
{
f[f1]=f2;
node[f2].sum=temp2;
node[f2].cnt+=node[f1].cnt;
}
}
printf("%lld\n",node[find(1)].sum);
}
return 0;
}