【hdu】1520 Anniversary party【树形dp】

来源:互联网 发布:ubuntu下安装虚拟机 编辑:程序博客网 时间:2024/05/21 11:32

题意:

一群人种有上下属关系,构成了一棵树,每个人都有一个价值,直接的上下属不能被加入同一个集合,问一个集合最大能有多少价值

题解:

赤裸裸的树形dp,这是我系统的开始学树形dp的第一道题,算是领略了一些树形dp的要点

dp[i][0]记录不取i节点所能得到的在以i节点为根的子树中所能取得的最大价值,dp[i][1]记录取i节点以i节点为跟所能取得的最大价值

遍历i的儿子 dp[i][0]+=max(dp[i][1],dp[i][0])  

dp[i][1]+=dp[v][0]

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N=6005;int dp[N][2],v[N],in[N],NE,head[N];struct node{    int v,next;}edge[N<<1];void init(){    memset(head,-1,sizeof(head));    NE=0;}void add(int u,int v){    edge[NE].v=v;    edge[NE].next=head[u];    head[u]=NE++;}int dfs(int u){    dp[u][0]=0;//初始化    dp[u][1]=v[u];    for(int i=head[u];i!=-1;i=edge[i].next){        int v=edge[i].v;        dfs(v);        dp[u][0]+=max(dp[v][0],dp[v][1]);//不取u        dp[u][1]+=dp[v][0];//取u就不能取v了    }    return max(dp[u][0],dp[u][1]);}int main(){    int n,a,b;    while(scanf("%d",&n)!=EOF){        init();        for(int i=1;i<=n;i++){            in[i]=0;            scanf("%d",&v[i]);        }        while(scanf("%d%d",&a,&b)&&a+b){            add(b,a);//b是a的爸爸            in[a]++;        }        int ans=0;        for(int i=1;i<=n;i++)            if(!in[i])ans+=dfs(i);//如果当前节点是根节点        printf("%d\n",ans);    }    return 0;}


0 0