POJ 2342 树形 DP

题意

传送门 POJ 2342

题解

d p [ i ] [ j ] dp[i][j] dp[i][j] 代表节点 1 1 1 取( j = 1 j=1 j=1)或不取( j = 0 j=0 j=0)的最大值,则有
{ d p [ i ] [ 0 ] = ∑ j 为 i 子 节 点 m a x { d p [ j ] [ 0 ] , d p [ j ] [ 1 ] } d p [ i ] [ 1 ] = r a t i n g [ i ] + ∑ j 为 i 子 节 点 d p [ j ] [ 0 ] \begin{cases}dp[i][0]=\sum_{j为i子节点} max\{dp[j][0],dp[j][1]\}\\ dp[i][1]=rating[i]+\sum_{j为i子节点} dp[j][0]\\ \end{cases} {dp[i][0]=jimax{dp[j][0],dp[j][1]}dp[i][1]=rating[i]+jidp[j][0]

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
#define maxn 6005
int N, ra[maxn], indeg[maxn], dp[maxn][2];
vector<int> G[maxn];

void dfs(int v)
{
    for (int i = 0; i < G[v].size(); i++)
    {
        int u = G[v][i];
        dfs(u);
        dp[v][0] += max(dp[u][0], dp[u][1]);
        dp[v][1] += dp[u][0];
    }
    dp[v][1] += ra[v];
}

int main()
{
    scanf("%d", &N);
    for (int i = 1; i <= N; i++)
    {
        scanf("%d", ra + i);
    }
    int u, v;
    while (~scanf("%d%d", &u, &v) && (u | v))
    {
        G[v].push_back(u);
        ++indeg[u];
    }
    int root = -1;
    for (int i = 1; i <= N; i++)
    {
        if (indeg[i] == 0)
        {
            root = i;
            break;
        }
    }
    dfs(root);
    printf("%d\n", max(dp[root][0], dp[root][1]));
    return 0;
}
©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页