没有上司的舞会(树形dp裸题)

题目 >>http://codevs.cn/problem/1380/

#include
#include
#include
#include
using namespace std;
const int MAXN = 2e5;
bool used[MAXN];
int n,a,b,num[MAXN],s,firs[MAXN],ans,nex[MAXN],dp[MAXN][2],cnt = 0;
struct zt
{
    int f,t;
}road[MAXN];
void build(int f,int t)
{
    road[++cnt] = (zt){f,t};
    nex[cnt] = firs[f];
    firs[f] = cnt;
}
int dfs(int x,int d) //表示x 去(d == 1)还是不去(d == 0)。 
{
    int ans = 0;
    for(int i = firs[x];i != -1; i = nex[i])
    {
        int v = road[i].t;
        if(!dp[v][0])
            dp[v][0] = dfs(v,0); // 记忆化,表示该状态下dp[编号][去与否]的最大值 
        if(!dp[v][1])
            dp[v][1] = dfs(v,1);
        if(d)
            ans += dp[v][0]; //上司去。 
        else
            ans += max(dp[v][0],dp[v][1]);//上司不去,若其下有更优解他也可能不去。 
    }
    if(d)
        return ans + num[x];//x 若去要加上他自己。 
    return ans;
}
int main()
{
    scanf("%d",&n);
    for(int i = 1;i <= n; i++)
        scanf("%d",&num[i]),firs[i] = -1;
    for(int i = 1;i < n; i++)
    {
        scanf("%d%d",&a,&b);
        build(b,a); // 建立上下级关系的图 
        used[a] = 1;
    }
    scanf("%d%d",&a,&b);
    for(int i = 1;i <= n;i ++)
        if(!used[i])
        {
            s = i; //找到大boss(根节点)。
            break;
        }
    ans = max(dfs(s,0),dfs(s,1)); // 分别计算大boss去还是不去。 
    printf("%d",ans);
} 

你可能感兴趣的:(dp,树形dp)