Timus 1039 树形DP
简单的树形DP,状态转移方程如下:
令res[i]表示以i为根的子树获得的最大值;第i个人去或者不去。
去的话,res[i]=value[i]+∑res[j], j表示i的孩子的孩子;
不去的话,res[i]=∑res[k],k表示i的孩子;
因此,res[i]=max{value[i]+∑res[j],∑res[k]};
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAX 123456789
struct node
{
int i,next;
}vert[6001];
int res[6001],head[6001],value[6001],father[6001],N;
int max(int a,int b)
{
return a > b ? a : b;
}
int dfs(int root)
{
int j,w,l,sum1=0,sum2=0;
if(head[root]==0)
{
res[root]=value[root] > 0 ? value[root] : 0;
return res[root];
}
for(j=head[root];j;j=vert[j].next)
{
w=vert[j].i;
sum1+=dfs(w);
for(l=head[w];l;l=vert[l].next)
sum2+=res[vert[l].i];
}
res[root]=max(sum2+value[root],sum1);
return res[root];
}
int add(int s,int t)
{
vert[N].i=t;
vert[N].next=head[s];
return N++;
}
int main()
{
int i,n,root,s,t;
while(scanf("%d",&n) && n)
{
N=1;
memset(head,0,sizeof(head));
memset(father,0,sizeof(father));
for(i=1;i<=n;i++) scanf("%d",&value[i]);
for(i=1;i<n;i++)
{
scanf("%d %d",&s,&t);
head[t]=add(t,s);
father[s]=t;
}
root=1;
while(father[root])
root=father[root];
printf("%d\n",dfs(root));
}
return 0;
}