在思想的天空里自由翱翔。

[周年庆宴 Hdu 1520(没有上司的舞会)]题解

Posted on 2023-06-30 19:49  rayhjfjwl  阅读(16)  评论(0)    收藏  举报

这是一道树形dp题,dp[i][0]代表这个职员不来,dp[i][1]代表这个职员来。当这个职员要来的话,他的所有直接下属都是不会来的,当这个职员不来的话,他的所有直接下属可以来也可以不来。我们就可以写出状态转移方程式dp[u][1] = Σdp[v][0],dp[u][0] = Σmax(dp[v][0],dp[v][1])。其中 u 代表当前节点, v 表示子节点。

#include
using namespace std;
int a[6005];
vector< int >road[6005];
int dp[6005][2];
int dfs( int u, int flag)
{
    if (dp[u][flag])
    {
        return dp[u][flag];
    } //记忆化
    if (flag)
    {
        dp[u][flag] = a[u];
        for ( int i = 0;i < road[u].size();i++)
        {
            int v = road[u][i];
            dp[u][flag] += dfs(v,!flag);
        }
      //当前节点来
    }
    else
    {
        for ( int i = 0;i < road[u].size();i++)
        {
            int v = road[u][i];
            dp[u][flag] += max(dfs(v,flag),dfs(v,!flag));
        }
      //当前节点不来
    }
    return dp[u][flag];
}
bool flag[6005];
int main(){
    int n;
    cin >> n;
    for ( int i = 1;i <= n;i++)
    {
        cin >> a[i]; //来后的开心值
    }
    for ( int i = 1;i < n;i++)
    {
        int x,y;
        cin >> x >> y;
        road[y].push_back(x); //x是y的直接下属
        flag[x] =  true ;
    }
    int id = 0;
    for ( int i = 1;i <= n;i++)
    {
        if (!flag[i])
        {
            id = i;
            break ;
        }
    } //找最大的老板
    cout << max(dfs(id,0),dfs(id,1)); //最大的老板来或不来取最大值
    return 0;
}