Codeforces Round #526 (Div. 1) A. The Fair Nut and the Best Path(树形DP)

题目链接
在这里插入图片描述
在这里插入图片描述
题意:给定n个点的树,树上每个点都有点权,每条边有边权,要求找出树上的两个点,两点间点权之和减去边权之和最大。
思路:第一遍dfs先求u的子树到u的最大值,第二遍dfs看看除了子树以外的边能否更新最大值,这里要注意一下子树中两点的和,其实我这个做法有点多余了,好像只要记录u的子树的最大值和次大值就可以了。。。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=3e5+5;
vector<pair<int,ll>>g[maxn];
ll ans=0,w,dp[maxn],a[maxn];
map<int,int>p;
void dfs(int x,int fa)
{
	dp[x]=a[x];
	ll max1=0,max2=0;
	for(auto to:g[x])
	{
		if(to.first==fa) continue;
		dfs(to.first,x);
		if(dp[x]<dp[to.first]+a[x]-to.second) dp[x]=dp[to.first]+a[x]-to.second,max1=dp[x],p[x]=to.first;
		else if(dp[x]==dp[to.first]+a[x]-to.second) max2=max1;
		else if(max2<dp[to.first]+a[x]-to.second) max2=dp[to.first]+a[x]-to.second;
	}
	ans=max(ans,max1+max2-a[x]);
}
void dfs2(int x,int fa,ll t)
{
	if(p[fa]!=x) 
	{
		if(dp[x]<dp[fa]+a[x]-t) dp[x]=dp[fa]+a[x]-t,p[x]=fa;
	}
	for(auto to:g[x])
	{
		if(to.first==fa) continue;
		dfs2(to.first,x,to.second);
	}
}
int main()
{
	int n,u,v;
	scanf("%d",&n);
	for(int i=1;i<=n;++i) scanf("%lld",&a[i]);
	for(int i=1;i<n;++i)
	{
		scanf("%d %d %lld",&u,&v,&w);
		g[u].push_back({v,w});
		g[v].push_back({u,w});
	}
	dfs(1,0);
	dfs2(1,0,0);
	for(int i=1;i<=n;++i) ans=max(ans,dp[i]);
	printf("%lld\n",ans);
}
发布了391 篇原创文章 · 获赞 1 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_42479630/article/details/105459142