这里有一个对树形dp简单的介绍:http://wenku.baidu.com/view/03d35d1c59eef8c75fbfb3b4.html
暂时的理解是如果题目中的数据具有层次结构(如树)等,且要求最优解,则可以考虑使用树形dp。
这道题可以简单的描述为有一些数据之间有父子关系,现在需要选择一些数据出来,使数据总的和最大,但要求数据两两之间不能有直接的父子关系。若设节点i为某一个根,则可以设dp[i][0]表示不包括i的子树的最大和,dp[i][1]表示包括节点i的子树的最大和。则最终所求的结果为:
ans=max{dp[i][0],dp[i][1]}
暂时的理解是如果题目中的数据具有层次结构(如树)等,且要求最优解,则可以考虑使用树形dp。
这道题可以简单的描述为有一些数据之间有父子关系,现在需要选择一些数据出来,使数据总的和最大,但要求数据两两之间不能有直接的父子关系。若设节点i为某一个根,则可以设dp[i][0]表示不包括i的子树的最大和,dp[i][1]表示包括节点i的子树的最大和。则最终所求的结果为:
ans=max{dp[i][0],dp[i][1]}
dp[i][0]=sum(max{dp[j][0],dp[j][1]}) //如果不包括i,则其子树的最大和是不包括其孩子
//或者包括其孩子两种可能下的最大和
dp[i][1]=sum(dp[j][0]) //如果包括i,则只能是不包括其孩子的最大和
AC_CODE:
#include <stdio.h>
#include <memory.h>
#define N 6005
struct node
{
int v;
node *next;
};
node *vertices[N],edges[N];
int rating[N];
int dp[N][2];
int ind[N];
int cnt;
void dfs(int u)
{
if(!vertices[u])
{
dp[u][0]=0;
dp[u][1]=rating[u];
return;
}
int v;
dp[u][1]+=rating[u];
for(node *n=vertices[u];n;n=n->next)
{
v=n->v;
dfs(v);
dp[u][0]+=(dp[v][0]<dp[v][1])?dp[v][1]:dp[v][0];
dp[u][1]+=dp[v][0];
}
}
int main()
{
int n,L,K,root;
while(scanf("%d",&n)!=EOF)
{
cnt=0;
memset(vertices,0,sizeof(vertices));
memset(dp,0,sizeof(dp));
memset(ind,0,sizeof(ind));
for(int i=1;i<=n;i++)
scanf("%d",&rating[i]);
while(scanf("%d%d",&L,&K)&&(L||K))
{
edges[cnt].v=L;
edges[cnt].next=vertices[K];
vertices[K]=&edges[cnt++];
ind[L]++;
}
for(root=1;root<=n;root++)
{
if(!ind[root])
{
dfs(root);
break;
}
}
printf("%d\n",(dp[root][0]>dp[root][1])?dp[root][0]:dp[root][1]);
}
return 0;
}