树形DP——洛谷 P1122

树形DP——洛谷 P1122

这道题也是通过dfs来对树进行遍历,通过回溯的方式先把一个树的所有子树的值求出来,然后如果这个子树是负值那么加入到树会让树的总值变小,如果是正值则加入。所以通过算出这个树的所有子树的值,进行有选择的加入这个树,然后算出这个树的值。

但是这个方法有个缺点。例如这个树就只有两个点-3, -4。然后我们选择了-4为根节点,然后dfs回溯的时候我们判断-3这个子树为负数可以减掉,做出来的是-4 。 但其实真正答案是-3 。所以我们要预处理下,选择最大的值为根节点进行搜索。

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long ll;
const int MAXN = 16000+10;
ll val[MAXN];

struct Edge{
    int v, next; 
}edge[MAXN<<1];
int cnt;
int head[MAXN];
int ans = -2147483648;
void addEdge(int u, int v)
{
    edge[cnt].v = v;
    edge[cnt].next = head[u];
    head[u] = cnt++;
    return;
}

int dfs(int u, int fa)
{
    ll now = val[u];
    for(int i = head[u]; ~i; i = edge[i].next)
    {
        int v = edge[i].v;
        if(v == fa)        continue;
        now += dfs(v, u);
    }
    if(now > ans)
        ans = now;
    if(now < 0)
        return 0;
    else     
        return now;
}


void ini(int n)
{
    for(int i = 1; i <= n; i++)
        head[i] = -1;
    cnt = 0;
    return;
}
int main()
{
    int n;
    scanf("%d", &n);
    ini(n);
    int root;
    ll maxtemp = -2147483648;
    for(int i = 1; i <= n; i++)
    {
        scanf("%lld", &val[i]);
        if(val[i] >= maxtemp)
        {
            maxtemp = val[i];
            root = i;
        }
    }
        
    int u, v;
    for(int i = 1; i < n; i++)
    {
        scanf("%d %d", &u, &v);
        addEdge(u, v);
        addEdge(v, u);
    }    
    dfs(root, 0);
    cout << ans;
    return 0;
} 

 

上一篇:P1122


下一篇:P1122 最大子树和