CodeForces - 1092F Tree with Maximum Cost
Posted on 2022-11-12 15:07 Capterlliar 阅读(24) 评论(0) 编辑 收藏 举报题意:给出一棵树,每个结点有一个权值。定义一棵树以ai为根节点的价值为 剩下每个结点到根节点的距离乘权值 之和。求这棵树的最大价值。
解:随便选一个结点为根,从下到上统计当前价值,设son[i]为以i结点为子树根节点,这颗子树价值乘路径长度之和。考虑换根,令当前根ai的一个子节点aj为新的根,ai变成aj的子树。dp[ai]减去aj的贡献,aj原子节点深度减一,贡献减son[aj];剩下的结点深度加一,贡献加sum-son[aj].
代码:
#include <bits/stdc++.h> using namespace std; #define maxx 200005 #define maxn 25 #define maxm 205 #define ll long long #define inf 1000000009 #define mod 2520 struct edge{ int u,v,w,next; }e[maxx*2]; int head[maxx]={0},cnt=0; void add(int u,int v){ e[++cnt].u=u;e[cnt].v=v;e[cnt].next=head[u];head[u]=cnt; } int n; ll ans=0,sum=0; ll dp[maxx]={0}; ll son[maxx]={0}; ll a[maxx]; void dfs1(int now,int fa,int d){ dp[now]=d*a[now]; son[now]=a[now]; for(int i=head[now];i;i=e[i].next){ int to=e[i].v; if(to==fa) continue; dfs1(to,now,d+1); dp[now]+=dp[to]; son[now]+=son[to]; } } void dfs2(int now,int fa){ ans=max(ans,dp[now]); for(int i=head[now];i;i=e[i].next){ int to=e[i].v; if(to==fa) continue; dp[now]-=dp[to]; dp[to]-=son[to]; dp[to]+=(dp[now]+sum-son[to]); dfs2(to,now); dp[to]-=(dp[now]+sum-son[to]); dp[to]+=son[to]; dp[now]+=dp[to]; } } signed main() { scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); sum+=a[i]; } for(int i=1;i<=n-1;i++){ int x,y; scanf("%d%d",&x,&y); add(x,y); add(y,x); } dfs1(1,0,0); dfs2(1,0); printf("%lld\n",ans); return 0; }