[UPC] Radio Prize | 换根dp

本文介绍了一种计算问题,涉及Treeland地区的n个城市,由n-1条道路连接,每条道路都有特定税率。主持人决定根据粉丝邮件数量奖励旅行套餐,每个城市的成本包括路径税。文章详细阐述了如何通过树形dp预处理和转移来计算赢得比赛的城市购买所有门票的总成本。
摘要由CSDN通过智能技术生成

题目描述

All boring tree-shaped lands are alike, while all exciting tree-shaped lands are exciting in their own special ways.What makes Treeland more exciting than the other tree-shaped lands are the raddest radio hosts in the local area: Root and Leaf. Every morning on FM 32.33 (repeating of course), Root and Leaf of The Full Depth Morning Show serve up the hottest celebrity gossip and traffic updates.
The region of Treeland is made of n cities, connected by n-1 roads such that between every pair of cities there is exactly one simple path. The i-th road connects cities ui and vi , and has a toll of wi.
To reward their loyal listeners, The Full Depth Morning Show is giving away a number of travel packages! Root and Leaf will choose n n 1 lucky residents from the city that sends them the most fan mail. Each of those residents then gets a distinct ticket to a different city in Treeland.
Each city in Treeland has its own tax on prizes: ti. Let du,v be the sum of the tolls on each road on the only simple path from city u to v. For a trip from city u to city v, the cost of that trip is then ( t u + t v ) d u , v (tu + tv)d_{u,v} (tu+tv)du,v
在这里插入图片描述

The shock jocks haven’t quite thought through how much their prize is worth. They need to prepare a report to the radio executives, to summarize the expected costs. For each city that could win the prize, what is the total cost of purchasing all the tickets?

输入

The first line of input is a single integer n (1 ≤ n ≤ 100 000). The next line has n space-separated integers ti (1 ≤ ti ≤ 1 000), the tax in each city. The following n-1 lines each have 3 integers, ui, vi, wi, meaning the i-th road connects cities ui and vi (1 ≤ ui, vi ≤ n), with a toll of wi (1 ≤ wi ≤ 1 000).

输出

Output n lines. On the i-th line, output a single integer: the cost of purchasing tickets if city i wins the contest.

样例输入

【样例1】

5
2 5 3 4 1
1 2 2
2 4 5
4 3 3
5 2 6

【样例2】

6
4 3 3 4 3 3
1 3 2
2 1 1
1 4 6
4 5 6
6 4 2

样例输出

【样例1】

130
159
191
163
171

【样例2】

209
206
232
209
336
232

首先先把花费P的式子拆开,我们可以得到 p u , v = ( t [ u ] + t [ v ] ) ∗ d u , v = t [ u ] ∗ d u , v + t [ v ] ∗ d u , v p_{u,v} = (t[u] + t[v]) * d_{u,v} = t[u]*d_{u,v} + t[v]*d_{u,v} pu,v=(t[u]+t[v])du,v=t[u]du,v+t[v]du,v ,其中 d u , v d_{u,v} du,v表示两点之间的距离
关于几个数组:
dis[]:dis[x]表示除x之外所有节点与x之间的距离之和
disval[]:disval[x]表示除x之外所有节点到x之间的距离与给定权值的乘积的和

假设要求 u u u到其他点花费的总和,那么 P [ u ] = t [ u ] ∗ ∑ v d u , v + ∑ v ( t [ v ] ∗ d u , v ) P[u] = t[u]* \sum_{v} d_{u,v} + \sum_v(t[v]*d_{u,v}) P[u]=t[u]vdu,v+v(t[v]du,v),令 d i s [ u ] = ∑ v d u , v dis[u] = \sum_{v} d_{u,v} dis[u]=vdu,v d i s v a l [ u ] = ∑ v ( t [ v ] ∗ d u , v ) disval[u] = \sum_v(t[v]*d_{u,v}) disval[u]=v(t[v]du,v),则 P u = t [ u ] ∗ d i s [ u ] + d i s v a l [ u ] P_u = t[u]*dis[u] + disval[u] Pu=t[u]dis[u]+disval[u]

我们可以先预处理出以 u u u为根的子树中节点到 u u u点的距离总和以及以 u u u为根的子树中节点到 u u u点的距离与点权乘积之和。
假设父节点为 x x x,子节点为 y y y w x , y w_{x,y} wx,y来表示x,y之间的边权,则预处理的转移方程为 d i s [ x ] = d i s [ y ] + s u m N o d e [ y ]   ∗   w x , y dis[x]=dis[y]+sumNode[y]\ ∗\ w_{x,y} dis[x]=dis[y]+sumNode[y]  wx,y,这里的 s u m N o d e [ ] sumNode[] sumNode[]数组指的是子树中节点的数量。 d i s v a l [ x ] = d i s v a l [ y ] + s u m V a l [ y ]   ∗   w x , y disval[x] = disval[y] + sumVal[y]\ ∗\ w_{x,y} disval[x]=disval[y]+sumVal[y]  wx,y,这里的 s u m V a l sumVal sumVal数组指的是子树中节点点权之和。
然后通过换根dp的方式,转移出 d i s [ ] , d i s v a l [ ] dis[],disval[] dis[],disval[]数组。假设父节点为 x x x,子节点为 y y y,转移方程为 d i s [ y ] = d i s [ x ] − s u m N o d e [ y ]   ∗   w x , y + ( n − s u m N o d e [ y ] )   ∗   w x , y dis[y] = dis[x] - sumNode[y]\ ∗\ w_{x,y} + (n - sumNode[y])\ ∗\ w_{x,y} dis[y]=dis[x]sumNode[y]  wx,y+(nsumNode[y])  wx,y,这里的 n n n指的是节点的数量。 d i s v a l [ y ] = d i s v a l [ x ] − s u m V a l [ y ]   ∗   w x , y + ( t o t v a l − s u m V a l [ y ] )   ∗   w x , y disval[y] = disval[x] - sumVal[y]\ ∗\ w_{x,y} + (totval - sumVal[y])\ ∗\ w_{x,y} disval[y]=disval[x]sumVal[y]  wx,y+(totvalsumVal[y])  wx,y,这里的 t o t v a l totval totval指的是所有节点的点权总和

理顺一下思路,就是先预处理出 s u m N o d e , s u m V a l , d i s , d i s v a l sumNode,sumVal,dis,disval sumNode,sumVal,dis,disval四个数组,然后再通过树形dp的方式更新 d i s , d i s v a l dis,disval dis,disval两个数组,最后再通过转移方程得到结果

const int maxn = 1e6+7;
struct node {
	int v,w,nex;
} e[maxn];
bool vis[maxn];
ll dis[maxn],disval[maxn],a[maxn];
ll sumNode[maxn],sumVal[maxn];
ll totval;
int head[maxn];
int cnt = 0;
int n,m;
typedef pair<int,int> PII;
void init() {
	for(int i=1; i<=n; i++) {
		dis[i] = 0;
		head[i] = -1;
		vis[i] = 0;
	}
}
void add(int u,int v,int w) {
	e[cnt].v = v;
	e[cnt].nex = head[u];
	e[cnt].w = w;
	head[u] = cnt++;
}
void dfs1(int u,int fa) {
	for(int i=head[u]; ~i; i=e[i].nex) {
		int to = e[i].v;
		if(to == fa) continue;
		dfs1(to,u);
		sumNode[u] += sumNode[to];
		sumVal[u] += sumVal[to];
		dis[u] += dis[to] + sumNode[to] * e[i].w;
		disval[u] += disval[to] + sumVal[to] * e[i].w;
	}
	++ sumNode[u];
	sumVal[u] += a[u];
}
void dfs2(int u,int fa) {
	for(int i=head[u]; ~i; i=e[i].nex) {
		int to = e[i].v;
		if(to == fa) continue;
		dis[to] = dis[u] - e[i].w * sumNode[to] + e[i].w * (n - sumNode[to]);
		disval[to] = disval[u] - e[i].w * sumVal[to] + e[i].w * (totval - sumVal[to]);
		dfs2(to,u);
	}
}
int main() {
	n = read;
	m = n - 1;
//	init();
	Clear(dis,0);
	Clear(disval,0);
	Clear(sumVal,0);
	Clear(sumNode,0);
	Clear(head,-1);
	for(int i=1; i<=n; i++) {
		a[i] = read;
		totval += a[i];
	}
	for(int i = 1; i<=m; i++) {
		int u = read,v = read,w = read;
		add(u,v,w);
		add(v,u,w);
	}
	dfs1(1,0);
	dfs2(1,0);
	for(int i=1; i<=n; i++) {
		printf("%lld\n",dis[i] * a[i] + disval[i]);
	}
	return 0;
}

参考

https://blog.csdn.net/weixin_43634220/article/details/108916701

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值