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; }