CodeForces - 1092F Tree with Maximum Cost(树形dp)

这里是→→→题目链接   

You are given a tree consisting exactly of nn vertices. Tree is a connected undirected graph with n−1n−1 edges. Each vertex vv of this tree has a value avavassigned to it.

Let dist(x,y)dist(x,y) be the distance between the vertices xx and yy. The distance between the vertices is the number of edges on the simple path between them.

Let's define the cost of the tree as the following value: firstly, let's fix some vertex of the tree. Let it be vv. Then the cost of the tree is ∑i=1ndist(i,v)⋅ai∑i=1ndist(i,v)⋅ai.

Your task is to calculate the maximum possible cost of the tree if you can choose vvarbitrarily.

Input

The first line contains one integer nn, the number of vertices in the tree (1≤n≤2⋅1051≤n≤2⋅105).

The second line of the input contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤2⋅1051≤ai≤2⋅105), where aiai is the value of the vertex ii.

Each of the next n−1n−1 lines describes an edge of the tree. Edge ii is denoted by two integers uiui and vivi, the labels of vertices it connects (1≤ui,vi≤n1≤ui,vi≤n, ui≠viui≠vi).

It is guaranteed that the given edges form a tree.

Output

Print one integer — the maximum possible cost of the tree if you can choose any vertex as vv.

Examples

Input

8
9 4 1 7 10 1 6 5
1 2
2 3
1 4
1 5
5 6
5 7
5 8

Output

121

Input

1
1337

Output

0

Note

Picture corresponding to the first example: 

You can choose the vertex 3 as a root, then the answer will be 2⋅9+1⋅4+0⋅1+3⋅7+3⋅10+4⋅1+4⋅6+4⋅5=18+4+0+21+30+4+24+20=121

In the second example tree consists only of one vertex so the answer is always 0.

题目大意应该挺明确的,定义了一种新的距离vv  那就是两点之间的距离乘以终点的权值   现在让你在树中找一个点,树的节点都是有权值的,要求这个点到所有点的距离vv之和最大并且输出这个距离vv

我们先开两个数组  dp和val

dp[u]表示结果数组,即我们定义的距离vv, val[u]表示子树的权值

我们把树分成两部分,外部和内部,内部表示的是节点1的子树的节点,但不包括节点1 ,而外部则是剩下的所有节点

往子节点方向深入的话,其实是每向下深入一次都要靠近子节点,外部点距离都会全部++,到内部点距离都要--,  如果以点1所求出来的答案为基础,那么点1的子节点5的答案就是,dp[1]-内部的总权值+外部的总权值

我们先求出点的总权值sum,内部总权值就是 val[t],外部总权值则是 sum-val[t]

这样我们就可以得到状态转移方程

dp[t]=dp[x]-val[t]+(sum-val[t]);

但是dp数组和val数组要怎么更新呢?这是一个回溯的过程,每靠近一次父亲节点,到外部的点的距离就会减少1,而到内部点的距离就会增加1,所以dp每次都要加上一次val 

dp[x]+=val[t]+dp[t];
val[x]+=val[t];

奉上卑微的AC代码,Orz

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
const ll inf=0x3f3f3f3f;
const ll mm=2e5+5;
ll w[mm];
ll val[mm];//val[u]表示以u为根的子树的总权值 
ll dp[mm];//dp[u]表示u到所有点的 距离*终点权值 之和 
ll head[mm];
ll cnt=0;
ll n;
ll sum=0;
struct node{
	ll to;
	ll next;
}pp[mm<<1];
void add(ll x,ll y){
	pp[cnt].to=y;
	pp[cnt].next=head[x];
	head[x]=cnt++;
}

void dfs(ll x,ll pre){
	val[x]=w[x];
	for(ll i=head[x];~i;i=pp[i].next){
		ll t=pp[i].to;
		if(t==pre)continue;
		dfs(t,x);
		dp[x]+=val[t]+dp[t];//从下往上更新,每回溯一次,加一次val 
		val[x]+=val[t];//子树权值求和 
	}
}

ll res;
void Dfs(ll x,ll pre){
	for(ll i=head[x];~i;i=pp[i].next){
		ll t=pp[i].to;
		if(t==pre)continue;
		dp[t]=dp[x]-val[t]+(sum-val[t]);//从上往下更新,每深入一次,减一次val,离子节点更近则外部点距离全部增加一次 
		Dfs(t,x);
	}
	res=max(res,dp[x]);
} 

int main()
{
	ll n;
	scanf("%lld",&n);
	memset(head,-1,sizeof(head));
	for(ll i=1;i<=n;i++){
		scanf("%lld",&w[i]);
		sum+=w[i];
	}
	ll x,y;
	for(ll i=1;i<n;i++){
		scanf("%lld%lld",&x,&y);
		add(x,y);
		add(y,x);
	}
	
	dfs(1,-1);
	res=dp[1];
	Dfs(1,-1);
	printf("%lld\n",res); 

	return 0;
}

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值