CodeForces 1084D The Fair Nut and the Best Path(树形dp)

题目描述

The Fair Nut is going to travel to the Tree Country, in which there are n cities. Most of the land of this country is covered by forest. Furthermore, the local road system forms a tree (connected graph without cycles). Nut wants to rent a car in the city u and go by a simple path to city v. He hasn’t determined the path, so it’s time to do it. Note that chosen path can consist of only one vertex.

A filling station is located in every city. Because of strange law, Nut can buy only wi liters of gasoline in the i-th city. We can assume, that he has infinite money. Each road has a length, and as soon as Nut drives through this road, the amount of gasoline decreases by length. Of course, Nut can’t choose a path, which consists of roads, where he runs out of gasoline. He can buy gasoline in every visited city, even in the first and the last.

He also wants to find the maximum amount of gasoline that he can have at the end of the path. Help him: count it.

Input

The first line contains a single integer n (1≤n≤3⋅105) — the number of cities.

The second line contains n integers w1,w2,…,wn (0≤wi≤109) — the maximum amounts of liters of gasoline that Nut can buy in cities.

Each of the next n−1 lines describes road and contains three integers u, v, c (1≤u,v≤n, 1≤c≤109, u≠v), where u and v — cities that are connected by this road and c — its length.

It is guaranteed that graph of road connectivity is a tree.

Output

Print one number — the maximum amount of gasoline that he can have at the end of the path.

Examples

Input

3
1 3 3
1 2 2
1 3 2

Output

3

Input

5
6 3 2 5 0
1 2 10
2 3 3
2 4 1
1 5 1

Output

7

Note

The optimal way in the first example is 2→1→3.
在这里插入图片描述

The optimal way in the second example is 2→4.

在这里插入图片描述

题意:

就是类似于树的直径,看一下最大的路径权值,每经过一个点,这个路径的权值就会加上这个点的权重,同样的经过一条边,这个路径的权值就会减去这个边的权重,求这个树上的最大路径权值

思路:

以前咱们在求树的直径的时候就是开了两个数组 f1 和 f2 分别代表了以这个点为根节点的最大路径和次大路径,然后树的直径就是所有点的f1 + f2 取一个max,现在咱们同样也可以开两个数组,一个是最大一个是次大,这个最大的权值不就是f1 + f2 + w[i]吗,这个w[i]代表的是这个点的权重,比较容易想到,但是实现起来当时自己写的时候出了点问题,借鉴的别人的代码写的这个树形dp,发现这个代码比较清晰易懂,现在咱们就来看一下这个代码吧!

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 3e5+10,M = N*2;
typedef long long LL;
int h[N],e[M],ne[M],idx;
LL a[N],w[M];
LL f1[N],f2[N];
void add(int a,int b,int c) {
	e[idx] = b;
	w[idx] = c;
	ne[idx] = h[a];
	h[a] = idx++;
}
LL ans;
void dfs(int u,int fa) {
	LL t1=0,t2=0;//t1代表的是最大,t2代表的是次大
	for(int i=h[u]; i!=-1; i=ne[i]) {
		int j = e[i];
		if(j == fa) continue;
		dfs(j,u);
		if(f1[j]-w[i] >= t1) {
			t2 = t1;
			t1 = f1[j] - w[i];
		} else if(f1[j]-w[i] > t2) t2 = f1[j]-w[i];
	}
	f1[u] = t1 + a[u];//最后发现这个次大数组好像没啥用,开了一个临时变量就能完成他的功能了
	ans = max(ans,f1[u]+t2);//这个就相当于树的直径了
}
int main() {
	int n;
	while(~scanf("%d",&n)) {
		memset(h,-1,sizeof h);
		idx=0;
		ans = 0;
		memset(f1,0,sizeof f1);
		memset(f2,0,sizeof f2);
		for(int i=1; i<=n; i++) scanf("%lld",&a[i]);
		for(int i=1; i<n; i++) {
			int a,b,c;
			scanf("%d%d%d",&a,&b,&c);
			add(a,b,c);
			add(b,a,c);
		}
		dfs(1,-1);//其实这个地方从哪个点开始都一样
		cout<<ans<<endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宇智波一打七~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值