这周任务。。树型DP
题意:n个人,他们具有上下级的关系,他们每个人都有一个值,我们的目的是找这么一些人,使他们的和最大,并且他们不能是上下级的关系。就是我叫了你的上级或者下级,你就不能来了。。
都说是树型DP裸题。。可我连什么是树型DP都不知道T,T 好吧,看了别人的代码,才了解一点点。就是对你这棵树进行由叶子到根的DP。
这题DP思想很像hdu 2845。当前存在两种状态。对于i这个人,要么取要么不取。那么状态转移方程就是:dp[i][取]+=dp[i的每一个孩子][不取];dp[i][不取]+=max(dp[i的每一个孩子][取],dp[i的每一个孩子][不取]);
这里建树我用的(其实是看别人用的)是类似建边的思想。当然,也有人用vector。。我不会。。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int n,pos,flag[6010],dp[6010][2],list[6010],value[6010];
struct P{
int u,v,next;
}point[6010];
void add(int pa,int son){
point[pos].u=pa;
point[pos].v=son;
point[pos].next=list[pa];
list[pa]=pos++;
}
void dfs(int root){
if(list[root]==-1){
dp[root][1]=value[root];
dp[root][0]=0;
return ;
}
int now=list[root];
dp[root][0]=0;
dp[root][1]=value[root];
while(now!=-1){
dfs(point[now].v);
dp[root][1]+=dp[point[now].v][0];
dp[root][0]+=max(dp[point[now].v][0],dp[point[now].v][1]);
now=point[now].next;
}
}
int main(){
while(scanf("%d",&n)!=EOF){
for(int i=1;i<=n;i++){
scanf("%d",&value[i]);
}
pos=0;
int a,b;
memset(list,-1,sizeof(list));
memset(flag,0,sizeof(flag));
while(scanf("%d%d",&a,&b)&&(a&&b)){
add(b,a);
flag[a]=1;
}
a=1;
while(flag[a])a++;
int root=a;
dfs(root);
printf("%d\n",max(dp[root][1],dp[root][0]));
}
return 0;
}