P1122 最大子树和
思路:由于是一棵n节点,n-1边的图,所以必然没有环,那么从任何一个节点出发都必然达到另外一个节点。
如果子节点的dp大于0,那么父节点加上,否则砍掉(不加)
同时如果visit过了那就不用visit,总体复杂度为O(n)。
代码:
#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 = 16010;
int val[N];
vector<int> G[N];//存图
int dp[N];//每个节点的max值
bool vis[N];//是否经历
void dfs(int x)// x号节点
{
vis[x] = true;
dp[x] = val[x];
for (int i = 0; i < G[x].size(); i++)
{
int v = G[x][i];//子节点
if (vis[v])continue;
if (!vis[v])dfs(v);//没有就跑一遍
if (dp[v] > 0)dp[x] += dp[v];//如果ok那就加上
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int n; cin >> n;
for (int i = 1; i <= n; i++)cin >> val[i];
for (int i = 1; i < n; i++)
{
int u, v; cin >> u >> v;
G[u].push_back(v), G[v].push_back(u);
}
dfs(1);//任意一个节点都行
int maxn = INT_MIN;
for (int i = 1; i <= n; i++)maxn = max(maxn, dp[i]);
cout << maxn;
return 0;
}