codevs 1380

树形动态规划,记忆化搜索实现。

以校长为根建立一棵树。

f[i][0]表示第i个人不去参加,以他为根的子树的最大快乐指数。

f[i][1]表示第i个人去参加,以他为根的子树的最大快乐指数。

f[i][0]=∑max(f[j][0],f[j][1])(j是i的下属)

f[i][1]=∑f[j][0](j是i的下属)

注意如果f数组为负数时返回0。

#include<cstdio>
#include<cctype>
#include<vector>
using namespace std;
int read(){
    char c; while(!isdigit(c=getchar()) && c!='-');
    int x=0,y=1; if(c=='-') y=-1; else x=c-'0';
    while(isdigit(c=getchar())) x=x*10+c-'0'; return x*y;
}
vector<int> e[6001];
int r[6001],f[6001][2],vis[6001][2];
bool yes[6001];
int dfs(int o,int p){
    if(vis[o][p]) return f[o][p]; else vis[o][p]=1;
    for(int i=0;i<e[o].size();i+=1)
        if(p==1) f[o][p]+=dfs(e[o][i],0);
        else f[o][p]+=max(dfs(e[o][i],0),dfs(e[o][i],1));
    if(p) f[o][p]+=r[o];
    return f[o][p]>0? f[o][p]:f[o][p]=0;
}
int main(){
    int n=read();
    for(int i=1;i<=n;i+=1) r[i]=read();
    for(int i=1;i<n;i+=1){
        int x=read(),y=read();
        e[y].push_back(x); yes[x]=1;
    }
    for(int i=1;i<=n;i+=1)
        if(!yes[i]) printf("%d",max(dfs(i,0),dfs(i,1)));
    return 0;
}
原文地址:https://www.cnblogs.com/AmnesiacVisitor/p/7610206.html