Codeforces - The Fair Nut and the Best Path

题目链接:Codeforces - The Fair Nut and the Best Path


找一条权值最大的链。

显然我们可以树dp,dp[x][0/1]分别表示,最长路径在子树当中,最长路径一个点在子树当中,一个点在子树之外。然后就可以转移了。

每次找最大值和次大值。

dp[x][0]=a[x]+max
dp[x][1]=a[x]+max+max_s


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e5+10,M=N<<1;
int n,a[N],dp[N][2],res;
int head[N],nex[M],to[M],w[M],tot;
inline void ade(int a,int b,int c){
	to[++tot]=b; nex[tot]=head[a]; w[tot]=c; head[a]=tot;
}
inline void add(int a,int b,int c){ade(a,b,c);	ade(b,a,c);}
void dfs(int x,int fa){
	int mx1=0,mx2=0;
	for(int i=head[x];i;i=nex[i])	if(to[i]!=fa){
		dfs(to[i],x);
		if(dp[to[i]][0]-w[i]>mx1)	mx2=mx1,mx1=dp[to[i]][0]-w[i];
		else if(dp[to[i]][0]-w[i]>mx2)	mx2=dp[to[i]][0]-w[i];
	}
	dp[x][0]=a[x]+mx1;
	dp[x][1]=a[x]+mx1+mx2;
	res=max(res,max(dp[x][0],dp[x][1]));
}
signed main(){
	cin>>n;
	for(int i=1;i<=n;i++)	scanf("%lld",&a[i]);
	for(int i=1,a,b,c;i<n;i++)	scanf("%lld %lld %lld",&a,&b,&c),add(a,b,c);
	dfs(1,1);
	cout<<res;
	return 0;
}
发布了604 篇原创文章 · 获赞 242 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/104407236