[USACO10MAR] Great Cow Gathering G
题目描述
Bessie 正在计划一年一度的奶牛大集会,来自全国各地的奶牛将来参加这一次集会。当然,她会选择最方便的地点来举办这次集会。
每个奶牛居住在 N N N 个农场中的一个,这些农场由 N − 1 N-1 N−1 条道路连接,并且从任意一个农场都能够到达另外一个农场。道路 i i i 连接农场 A i A_i Ai 和 B i B_i Bi,长度为 L i L_i Li。集会可以在 N N N 个农场中的任意一个举行。另外,每个牛棚中居住着 C i C_i Ci 只奶牛。
在选择集会的地点的时候,Bessie 希望最大化方便的程度(也就是最小化不方便程度)。比如选择第 X X X 个农场作为集会地点,它的不方便程度是其它牛棚中每只奶牛去参加集会所走的路程之和(比如,农场 i i i 到达农场 X X X 的距离是 20 20 20,那么总路程就是 C i × 20 C_i\times 20 Ci×20)。帮助 Bessie 找出最方便的地点来举行大集会。
输入格式
第一行一个整数 N N N 。
第二到 N + 1 N+1 N+1 行:第 i + 1 i+1 i+1 行有一个整数 C i C_i Ci。
第 N + 2 N+2 N+2 行到 2 N 2N 2N 行:第 i + N + 1 i+N+1 i+N+1 行为 3 3 3 个整数: A i , B i A_i,B_i Ai,Bi 和 L i L_i Li。
输出格式
一行一个整数,表示最小的不方便值。
样例 #1
样例输入 #1
5
1
1
0
0
2
1 3 1
2 3 2
3 4 3
4 5 3
样例输出 #1
15
提示
1 ≤ N ≤ 1 0 5 1\leq N\leq 10^5 1≤N≤105, 1 ≤ A i ≤ B i ≤ N 1\leq A_i\leq B_i\leq N 1≤Ai≤Bi≤N, 0 ≤ C i , L i ≤ 1 0 3 0 \leq C_i,L_i \leq 10^3 0≤Ci,Li≤103。
思路
边带权点带权的一道 换根dp
是上一题STA-Station的ultra版
code
#include<bits/stdc++.h>
#define bl(i,a) for(long long i=head[a];i;i=nxt[i])
using namespace std;
const int N=2e6+3;
long long nxt[N],edge[N],head[N],dis[N],tot,n,c[N],sum,ans=1e17;
void add(int x,int y,int w){
nxt[++tot]=head[x];
head[x]=tot;
edge[tot]=y;
dis[tot]=w;
}
long long siz[N],f[N];
void getsiz(int me,int dad){
siz[me]=c[me];
bl(i,me){
int v=edge[i];
if(v==dad)continue;
getsiz(v,me);
siz[me]+=siz[v];
f[me]=f[me]+f[v]+siz[v]*dis[i];
}
}
long long d[N];
void dp(int me,int dad){
bl(i,me){
int v=edge[i];
if(v==dad)continue;
d[v]=1ll*d[me]-siz[v]*dis[i]+(sum-siz[v])*dis[i];
ans=min(d[v],ans);
dp(v,me);
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>c[i];sum+=c[i];
}
for(int i=1,l,r,w;i<n;i++){
cin>>l>>r>>w;
add(l,r,w);add(r,l,w);
}
getsiz(1,0);
d[1]=f[1];
dp(1,0);
cout<<ans;
}