树形DP第一题。首先定义dp[i][0]表示不选i号节点i子树能获取的最大值,dp[i][1]表示选i号节点i子树能获取的最大值。那么很容易的可以写出状态转移方程:
dp[i][0]+=max(dp[v][0],dp[v][1]);
dp[i][1]+=dp[v][0];
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=6010;
vector<int> g[maxn];
int val[maxn],in[maxn],dp[maxn][2];
int dfs(int rt)
{
dp[rt][0]=0;
dp[rt][1]=val[rt];
int len=g[rt].size();
for(int i=0;i<len;i++)
{
int v=g[rt][i];
dfs(v);
dp[rt][0]+=max(dp[v][0],dp[v][1]);
dp[rt][1]+=dp[v][0];
}
return max(dp[rt][0],dp[rt][1]);
}
int main()
{
int n,l,k;
while(~scanf("%d",&n))
{
memset(in,0,sizeof in);
for(int i=1;i<=n;i++) scanf("%d",&val[i]),g[i].clear();
while(~scanf("%d%d",&l,&k))
{
if(l==0&&k==0) break;
g[k].push_back(l);
in[l]++;
}
for(int i=1;i<=n;i++)
{
if(!in[i])
{
printf("%d\n",dfs(i));
break;
}
}
}
return 0;
}