牛客小白月赛22 B题(树的直径+dp)

题目链接
这个题目找最长的链其实就是找树的直径,不过需要注意的是一般求树的直径,长度一般都是边的权值相加,但这里是点的权值相加。接着就开始求最长链了。
如何求最长链?首先我们要建立一个无向图,把所有的点和边连接起来,然后开始尝试经过每一个点的最长链,从而找到最长的链。求经过某个点的最长链时,我们可以先求出从这个点出发可以到达的最远距离,然后再找出从这个点出发的第二远的距离,最后将两者相加即可得到经过该点的最长链。
然后不断更新最长链即可得到答案。
在求经过某点到达的最远距离时,是基于一个动态规划的思想
在这里插入图片描述
D[x]为从x出发可到达的最远距离。
最后即可得到结果

实现代码

#include
#include
#include
using namespace std;
const int maxn=1e5+10;
const int inf=1e9+10;
typedef long long ll;
ll n,ans;
ll a[maxn],dp[maxn];
vector<int> e[maxn];
void dfs(int u,int be){
	ll tmp1,tmp2;
	tmp1=tmp2=a[u];
	for(int i=0;i<e[u].size();i++){
		int v=e[u][i];
		if(v==be) continue;
		dfs(v,u);
		if(dp[v]+a[u]>tmp1){
			tmp2=tmp1;
			tmp1=dp[v]+a[u];
		}
		else if(dp[v]+a[u]>tmp2){
			tmp2=dp[v]+a[u];
		}
	}
	dp[u]=tmp1;
	ans=max(ans,tmp1+tmp2-a[u]);
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);	
	cin>>n;
	for(int i=1;i<=n;i++) {
		cin>>a[i];
	}
	for(int i=0;i<n-1;i++){
		int u,v;
		cin>>u>>v;
		e[u].push_back(v);
		e[v].push_back(u);
	}
	ans=-inf;
	dfs(1,-1);
	cout<<ans<<endl;
	
	return 0;
} 

你可能感兴趣的:(训练)