http://acm.hdu.edu.cn/showproblem.php?pid=1520
树上dp
dp[i][0]表示编号为i的人不去,dp[i][1]表示编号为i的人去
设i下属为j
如果i去,他的下属一定不去;dp[i][1]加dp[j][0]
如果i不去,他的下属可以去可以不去;dp[i][0]加max(dp[i][0],dp[i][1])
#include <stdio.h>
#include <algorithm>
#include <string.h>
#define maxn 6010
#define mem(x,y) memset(x,y,sizeof x)
using namespace std;
struct node{int next;int to;};
node e[maxn];
int n,m,cnt,dp[maxn][2],head[maxn];
bool flag[maxn];
void add(int x,int y)
{
e[++cnt].next=head[x];
e[cnt].to=y;
head[x]=cnt;
}
void dfs(int u)
{
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
dfs(v);
dp[u][0]+=max(dp[v][1],dp[v][0]);
dp[u][1]+=dp[v][0];
}
}
int main()
{
while(~scanf("%d",&n))
{
cnt=0;
mem(flag,false);
mem(dp,0);
mem(head,-1);
for(int i=1;i<=n;i++)
scanf("%d",&dp[i][1]);
int l,k;
while(~scanf("%d%d",&l,&k))
{
if(l==0&&k==0) break;
add(k,l);
flag[l]=true;
}
int root;
for(int i=1;i<=n;i++)
if(!flag[i])
{root=i;break;}
dfs(root);
printf("%d\n",max(dp[root][0],dp[root][1]));
}
return 0;
}