Luogu U18740

Luogu U18740 古墓丽影

题意概括:以某个点为根时,其他每个点到它的距离*它的点权的和的最小值。

这题是带权重心的裸题。

DFS即可。

#include<cstdio>
#include<iostream>
#include<algorithm>
#define ll long long
#define maxn 200010
using namespace std;
struct Edge{
    ll int to,next,d;
}e[maxn*2];
ll int w[maxn],head[maxn],tot,size[maxn],Maxsize[maxn],ans=0,n,root;
ll int read(){
    ll int w=0;char c=getchar();
    while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') w=w*10+c-48,c=getchar();
    return w;
}
void add(ll int x,ll int y,ll int dis){
    e[++tot]=(Edge){y,head[x],dis};
    head[x]=tot;
}
inline void getroot(ll int x,ll int fa){
    size[x]=1;Maxsize[x]=0;
    for(ll int i=head[x];i;i=e[i].next){
        if(e[i].to!=fa){
            getroot(e[i].to,x);size[x]+=size[e[i].to];Maxsize[x]=max(Maxsize[x],size[e[i].to]);
        }
    }
    Maxsize[x]=max(Maxsize[x],n-size[x]);
    if(Maxsize[x]<Maxsize[root]) root=x;
}
inline void calculate(ll int x,ll int dis,ll int fa){
    for(ll int i=head[x];i;i=e[i].next){
        if(e[i].to!=fa){ans+=w[e[i].to]*(dis+e[i].d);calculate(e[i].to,dis+e[i].d,x);}
    }
}
int main(){
    ll int i,x,y,distant;
    n=read();
    for(i=1;i<=n-1;i++){
        x=read();y=read();distant=read();
        add(x,y,distant);add(y,x,distant);
    }
    for(i=1;i<=n;i++){
        w[i]=read();
    }
    Maxsize[0]=n+1;
    getroot(1,0);
//    printf("%d",root);
    calculate(root,0,0);
    printf("%lld",ans);
    return 0;
}
古墓丽影

 

posted @ 2018-01-29 20:41  Konnyaku  阅读(191)  评论(0编辑  收藏  举报