树形dp入门题,dp[i][1] 表示选择i结点的最大值,dp[i][0]表示不选i结点的最大值。
则方程为
dp[i][1] += dp[i的所有孩子][0] (依题意,i选了,i的孩子就一定不能选)
dp[i][0] += max(dp[i的所有孩子][0],dp[i的所有孩子][1]) (i不选,则他的孩子可以选,也可以不选,我们选择二者的最大值)
存图的时候我用了一个vector的二维数组存下每个结点所有的孩子数。
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
int rank[6005];
vector<int> son[6005];
bool isroot[6005];
int dp[6005][2];
int n;
void treedp(int k)
{
if(son[k].size()==0)
{
dp[k][1]=rank[k];
dp[k][0]=0;
return;
}
dp[k][0]=0;
dp[k][1]=rank[k];
for(int i=0;i<son[k].size();i++)
{
treedp(son[k][i]);
dp[k][1]+=dp[son[k][i]][0];
dp[k][0]+=max(dp[son[k][i]][1],dp[son[k][i]][0]);
}
}
int main()
{
int l,k;
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)
{
scanf("%d",&rank[i]);
son[i].clear();
}
memset(isroot,0,sizeof(isroot));
while(scanf("%d%d",&l,&k)&&(l||k))
{
son[k].push_back(l);
isroot[l]=1;
}
int i;
for(i=1;i<=n;i++)
{
if(!isroot[i])
{
treedp(i);
break;
}
}
printf("%d\n",max(dp[i][1],dp[i][0]));
}
return 0;
}