b_lq_生命之树(树形最大字段和)

上帝要在这棵树内选出一个非空节点集 S,使得对于 S 中的任意两个点 a,b,都存在一个点列 {a,v1,v2,…,vk,b} 使得这个点列中的每个点都是 S 里面的元素,且序列中相邻两个点间有一条边相连。
在这个前提下,上帝要使得 S 中的点所对应的整数的和尽量大。
求出这棵树的最大的和

思路

if (f[v]>0) f[u]+=f[v],v是u的子节点

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
ll n, ans=LONG_MIN, a[N], st[N], f[N];
vector<int> g[N];
void dfs(int u) {
    st[u]=1;
    for (int v : g[u]) if (!st[v]) {
        dfs(v);
        if (f[v]>0) 
            f[u]+=f[v];
    }
    if (f[u]>ans) ans=f[u];
}
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin>>n; for (int i=1; i<=n; i++) cin>>a[i], f[i]=a[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);
    cout<<ans;
    return 0;
}
原文地址:https://www.cnblogs.com/wdt1/p/13765542.html