P8625 [蓝桥杯 2015 省 B] 生命之树

题目:
链接:https://www.luogu.com.cn/problem/P8625
基本思路:
1.使用dp[N]记录i节点的当前最大值
2.使用vectornex[N]记录图
3.使用vis[N]防回退
如果该节点没有子节点,那么这个点的最大值就记录为当前的值:val
如果该节点有子节点,那么先遍历子节点,然后+res并记录
由于使用了vis,那么就保证不会出现重复加和某一树节点的情况,所以不用减去某个树叶的值
证明:如果k节点的子节点j最大值是大于0,
1.当k节点<0时,j节点的max不用加val[k],会遍历到dp[j];
2.当k节点>0,j节点max加上val[k]存在dp[k]中。
所以一定不用减去
代码

#include<iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<sstream>
#include<string>
#include<string.h>
#include<iomanip>
#include<stdlib.h>
#include<map>
#include<queue>
#include<limits.h>
#include<climits>
#include<fstream>
#include<stack>
typedef long long ll;
using namespace std;

const int N = 1e5 + 2;
ll val[N];
int n;
ll dp[N];
vector<int>nex[N];
bool vis[N];

ll dfs(int k)
{
	//k:point
	vis[k] = 1;
	if (dp[k]!=0)return dp[k];
	ll res = val[k];
	if (nex[k].size() == 0)res = val[k];
	else
		for (int i = 0; i < nex[k].size(); i++)
			if (!vis[nex[k][i]] and dfs(nex[k][i]) >= 0)
			{
				res = res + dfs(nex[k][i]);
			}
	
	return dp[k] = res;
}

int main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin >> n;
	for (int i = 1; i <= n; i++)cin >> val[i];
	int from, to;
	for (int i = 0; i < n - 1; i++) { cin >> from >> to; nex[from].push_back(to); nex[to].push_back(from); }
	ll maxn = 0;
	for (int i = 1; i <= n; i++)
		maxn = max(dfs(i), maxn);//按序遍历,怎么遍历都行
	cout << maxn;
	return 0;
}

posted on 2024-04-09 20:38  WHUStar  阅读(9)  评论(0编辑  收藏  举报