题意:一个森林,每个节点都有一个值,每个节点和他的父节点不能同时出现,求出现的节点的值的和的最大值。
思路:dp[i][j] 为以i为根节点的树的最大值的和,j = 0说明根节点存在,j =1说明不存在。
我的代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = 6005;
int n,rat[maxn],par[maxn],deg[maxn],dp[maxn][2];
queue<int> que;
void init()
{
memset(par,-1,sizeof(par));
memset(dp,0,sizeof(dp));
memset(deg,0,sizeof(deg));
}
int main()
{
int i,l,k,u,v,res;
while(~scanf("%d",&n))
{
init();res = 0;
for(i = 1; i <= n; i++) scanf("%d",&rat[i]);
while(scanf("%d%d",&l,&k),l+k)
{
par[l] = k ;
deg[k]++;
}
for(i = 1; i <= n; i++) if(!deg[i]) que.push(i);
while(!que.empty())
{
u = que.front();
que.pop();
dp[u][1] += rat[u];
v = par[u];
if(v != -1)
{
if(--deg[v] == 0) que.push(v);
}
else res += max(dp[u][0],dp[u][1]);
dp[v][1] += dp[u][0];
dp[v][0] += max(dp[u][0],dp[u][1]);
}
printf("%d\n",res);
}
return 0;
}