poj2342
先预热一下,开始先从这个入手,然后再做poj3342,实质都是一样的。
题意:输入的前n个单数是每个人的快乐程度,就当做价值吧,后n-1个是关系,最后以0 0 结束关系。求整体价值最大,要求他们每个人的关系不能是直接的上下属,即结点间不相邻。
注意: 价值 在这题中 有正有负 , 人数是<6000 ,整形sum 计算价值是足够的。
思想: 是结点对结点的递推,而不会一层对上一层的递推。
有两个状态,1 .结点u 和 它的子节点的子节点集
2 .结点u的子节点集
(那么就应该用两个空间变量去存储更新)
由于价值有正有负,要求它的最大值,那么,max()进行更新
每种状态求得的是 该结点的最大价值,由该节点去推 父节点和父父节点
#include<stdio.h>
#include<string.h>
#define max(a,b) a>b?a:b
int dp[6001][2],par[6001];
void dfs( int r ,int n)
{
int i,m;
for(i = 1;i <= n ;i++ )
{
if(par[i] == r)
{
dfs(i , n);
m = max(dp[i][0] , dp[i][1]);
dp[r][0] = max(dp[r][0] , m + dp[r][0]);
if(par[r]!=0)
dp[par[r]][1] = max(dp[par[r]][1] , m + dp[par[r]][1]);
}
}
}
int main()
{
int n,i,j;
int c,f,m,root;
while(scanf("%d",&n)!=EOF)
{
memset(par,0,sizeof(par));
memset(dp,0,sizeof(dp));
for(i= 1 ;i <= n;i++)
scanf("%d",&dp[i][1]);
root = 0;
for(i= 0;i<n;i++)
{
scanf("%d %d", &c ,&f);
if(c== 0 && f == 0)break;
par[c] =f;
if(par[f] == 0)root = f;
}
dfs(root , n);
m = max(dp[root][0] ,dp[root][1]);
printf("%d\n",m);
}
return 0;
}