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; }