【CF1092F】 Tree with Maximum Cost

题目

题目描述
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 a_va
v

assigned 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 \sum\limits_{i = 1}^{n} dist(i, v) \cdot a_i
i=1

n

dist(i,v)⋅a
i

.

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

输入格式
The first line contains one integer nn , the number of vertices in the tree ( 1 \le n \le 2 \cdot 10^51≤n≤2⋅10
5
).

The second line of the input contains nn integers a_1, a_2, \dots, a_na
1

,a
2

,…,a
n

( 1 \le a_i \le 2 \cdot 10^51≤a
i

≤2⋅10
5
), where a_ia
i

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 u_iu
i

and v_iv
i

, the labels of vertices it connects ( 1 \le u_i, v_i \le n1≤u
i

,v
i

≤n , u_i \ne v_iu
i



=v
i

).

It is guaranteed that the given edges form a tree.

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

题意翻译
有一n个节点的树,每个节点有一点权ai。

定义dist(x,y)为x到y的边数。

选取一点v,使\sum_{i=1}^{n}dist(i,v)*ai\qquad∑
i=1
n

dist(i,v)∗ai最大

第一行输入n;

第二行输入n个数ai;

接下来n-1行,每行两个数x,y表示x到y有一条边。

输出最大值。

输入输出样例
输入 #1复制
8
9 4 1 7 10 1 6 5
1 2
2 3
1 4
1 5
5 6
5 7
5 8
输出 #1复制
121
输入 #2复制
1
1337
输出 #2复制
0
说明/提示
Picture corresponding to the first example:

You can choose the vertex 33 as a root, then the answer will be 2 \cdot 9 + 1 \cdot 4 + 0 \cdot 1 + 3 \cdot 7 + 3 \cdot 10 + 4 \cdot 1 + 4 \cdot 6 + 4 \cdot 5 = 18 + 4 + 0 + 21 + 30 + 4 + 24 + 20 = 1212⋅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 00 .

思路

1.第一次扫描时,任选一个点为根,再“有根树”上执行一次树形DP,也就是回溯时发生的 自底向上的状态转移

2.第二次扫描时,从刚才任选的根出发,对整棵树执行一次深度优先遍历,在,每次递归钱进行自顶向下的推导,计算出换根后的新解

套路比较明显

来看这道题 要求我们选择一个点 使得其他点的深度乘权值之和最大

我们先以一号点为根然后进行预处理 求出来子树的权值和 以及1号节点为根的DP值

考虑第二次扫描

当我们枚举到u-v这条边时 图被分成两部分 画图很显然可得 u节点所在的部分深度都+1 v节点所在深度都-1

所以DP方程呼之欲出:

f[v]=f[u]+sum-size[v]-size[v]

O(n)DFS即可

代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+77;
int n,head[N],cnt;
ll siz[N],sum,f[N],ans=0,a[N],dep[N];
struct edge
{
	int nxt,to;
}e[N<<1];
void add(int x,int y){
	e[++cnt].nxt=head[x];
	e[cnt].to=y;
	head[x]=cnt;
}
void dfs1(int x,int fa){
	siz[x]=a[x];
	for(int i=head[x]; i; i=e[i].nxt){
		int v=e[i].to;
		if(v==fa) continue;
		dep[v]=dep[x]+1;
		f[1]=f[1]+(ll)(a[v]*dep[v]);
		dfs1(v,x);
		siz[x]+=siz[v];
	} 
}
void dfs2(int x,int fa){
	for(int i=head[x]; i; i=e[i].nxt){
		int y=e[i].to;
		if(y==fa) continue;
		f[y]=f[x]+sum-siz[y]-siz[y];
		dfs2(y,x);
	}
}
int main()
{
	n=read();
	for(int i=1; i<=n; i++)
	{
		a[i]=read();
		sum+=a[i];
	}
	for(int i=1; i<n; i++)
	{
		int u,v;
		u=read(),v=read(); 
		add(u,v);
		add(v,u);
	}
	dfs1(1,0);
	dfs2(1,0);
	for(int i=1; i<=n; i++)
	{
		ans=max(f[i],ans);
	}
	printf("%lld",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值