ural1039 树形dp

一道很简单的树形dp,之前也是没有做过,从简单的开始做起。

题意:就是说公司要开个party,每个人都有一个欢乐值,条件是一个人如果到场那么它的直系上司不能在,问最大的欢乐值。

思路:建棵树,也可能是很多棵树,然后dp[i][1]表示第i个人的上司在,0代表上司不在。那么转移方程是

dp[i][0]=max(求和(dp[child][1])+w[i],求和(dp[child][0]))

dp[i][1]=求和(dp[child][0]);

边界处理,就是叶子节点。dp[i][0]=w[i],dp[i][1]=0;

然后一个dfs过一遍就好了。

代码:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=6005;

int dp[maxn][2];
int rat[maxn];
int in[maxn];
int out[maxn];
int n;

struct node{
    int v,next;
};
int  cnt;
int head[maxn];
node edge[maxn<<1];
void add(int a,int b){
edge[cnt].v=b;
edge[cnt].next=head[a];
head[a]=cnt++;
}

int dfs(int u,int f){
    int ans1=0,ans2=0;
    for(int i=head[u];i!=-1;i=edge[i].next){
      int v;
      v=edge[i].v;
      if(v==f) continue;
      dfs(v,u);
      ans1+=dp[v][1];
      ans2+=dp[v][0];
    }
    dp[u][0]=max(ans1+rat[u],ans2);
    dp[u][1]=ans2;
    return max(dp[u][0],dp[u][1]);
}

int main(){
    while(~scanf("%d",&n)){
    memset(head,-1,sizeof(head));
    memset(in,0,sizeof(in));
    memset(rat,0,sizeof(rat));
    memset(dp,0,sizeof(dp));
    cnt=0;
    for(int i=1;i<=n;i++){
        scanf("%d",&rat[i]);
    }
    int x,y;
    while(scanf("%d%d",&x,&y)){
        if(x==0&&y==0) break;
        add(y,x);
        add(x,y);
        in[x]++;
        out[y]++;
    }
    for(int i=1;i<=n;i++){
        if(out[i]==0){
            dp[i][0]=rat[i];
        }
    }
    int i,ans=0;
    for(i=1;i<=n;i++){
        if(in[i]==0){
            ans+=dfs(i,0);
        }
    }
    printf("%d\n",ans);
    }
return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值