zoj 3659 Conquer a New Region

时间:2021-09-22 04:00:30
// 给你一颗树 选一个点,从这个点出发到其它所有点的权值和最大
// i 到 j的最大权值为 i到j所经历的树边容量的最小值
// 第一感觉是树上的dp
// 后面发现不可以
// 看了题解说是并查集
// 然后发现这不就是在最小生成树那个模板上做其它操作吗、、
// 的确是好题
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <cmath>
#include <string.h>
using namespace std;
#define maxn 200010
#define LL long long
struct Eg{
int a,b,w;
bool operator<(const Eg &t)const{
return w>t.w;
}
}E[maxn<<];
int f[maxn];
LL cnt[maxn],sum[maxn];
int Find(int x){
if(x!=f[x])
f[x]=Find(f[x]);
return f[x];
}
int main(){
int n;
int i;
while(scanf("%d",&n)!=EOF){
for(i=;i<n-;i++)
scanf("%d %d %d",&E[i].a,&E[i].b,&E[i].w);
sort(E,E+n-);
for(i=;i<=n;i++){
f[i]=i;
cnt[i]=;
sum[i]=;
}
LL ans=;
int u,v;
LL su,sv;
for(i=;i<n-;i++){
u=Find(E[i].a);
v=Find(E[i].b);
su=cnt[v]*E[i].w+sum[u];
sv=cnt[u]*E[i].w+sum[v];
if(su>sv){
f[v]=u;
cnt[u]+=cnt[v];
sum[u]=su;
}else {
f[u]=v;
cnt[v]+=cnt[u];
sum[v]=sv;
}
ans=max(ans,max(su,sv));
}
printf("%lld\n",ans);
}
return ;
}