Soratosorato

ABC348E Minimize Sum of Distances 题解

Sorato·2024-06-13 19:41·17 次阅读

ABC348E Minimize Sum of Distances 题解

ABC348E Minimize Sum of Distances

题目大意#

给定一棵共 n 个节点的树, 第 i 个点的权重为 ci。定义 f(x) 表示树上所有点到节点 x 的距离乘上权重,即 f(x)=i=1n(ci×dis(x,i))。求 minu=1nf(u)

Solve#

一眼换根。

考虑先以节点 1 为根,则 f(1)=i=1n(ci×di),(di 表示 i 的深度)。然后考虑换根求 f(u),u[2,n]

image-20240409193224147

如图,以 u=2 时为例。记 sumu 为当以 1 为根时 u 的子树内的点的权值和。当根从 fa2=1 转移至 2 时,对于在 2 的子树里的节点,他们的深度都减少了 1,那么 ison2(ci×di) 就总共减少了 sumu;对于不在 2 的子树里的点,他们的深度都增加了 1,共增加 sum1sumu。整理一下并推广至所有 u[2,n],有: f(u)=f(fau)sumu+sum1sumu

Code#

Copy
#include<bits/stdc++.h> #pragma GCC optimize(1,2,3,"Ofast","inline") using namespace std; #define int long long inline int read() { short f=1; int x=0; char c=getchar(); while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();} while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,a,b,c[100010],f[100010],ans; vector<int>e[100010]; void dfs(int u,int fa,int d) { f[1]+=d*c[u]; for(auto i:e[u]) if(i!=fa) dfs(i,u,-~d),c[u]+=c[i]; } void dp(int u,int fa) { for(auto i:e[u]) if(i!=fa) f[i]=f[u]-c[i]+c[1]-c[i],dp(i,u); } signed main() { n=read(); for(int i=1;i<n;i=-~i) a=read(),b=read(), e[a].push_back(b),e[b].push_back(a); for(int i=1;i<=n;i=-~i) c[i]=read(); dfs(1,0,0);ans=f[1];dp(1,0); for(int i=1;i<=n;i=-~i) ans=min(ans,f[i]); return printf("%lld",ans),0; }
posted @   Sorato  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
点击右上角即可分享
微信分享提示
目录