hdu 4276 The Ghost Blows Light

先找到1到n的路,然后对这条路上的每个点进行一次树形dp,最后对路上的点再dp一次。
#include<stdio.h>
#include<vector>
#include<string.h>
#include<algorithm>
using namespace std;
vector<int> s[220];
int w[210]; int cost[110][110],mark[110]; int N,T,sign,tt;
int dp[210][510],f[110][510];
void Findroute(int u,int pre)
{
    int i,j;
    if(u==N) { mark[u]=1; sign=1; return;}
    for(i=0;i<s[u].size();i++)
    {
        if(sign) break;
        if( s[u][i] == pre) continue;
        Findroute(s[u][i],u);
        if(sign) tt+=cost[u][s[u][i]];
    }
    if(sign) mark[u]=1;
}
void dfs(int u,int pre,int MAX)
{
    dp[u][0]=w[u];
    for(int i=0;i<=MAX;i++) dp[u][i]=w[u];
    int i,j,k;
    for(i=0;i<s[u].size();i++)
    {
        if( mark[s[u][i]] || s[u][i]==pre ) continue;
        dfs(s[u][i],u,MAX);
        for(j=MAX;j>=0;j--)
            for(k=0;k<=j;k++)
            {
                if( j >= 2*cost[u][s[u][i]]+k )
                    dp[u][j]=max( dp[u][j-k-2*cost[u][s[u][i]]]+dp[s[u][i]][k],dp[u][j]);
            }
    }
}
int main()
{
    int i,j,k,a,b,t;
    while(scanf("%d%d",&N,&T)!=EOF)
    {
        memset(mark,0,sizeof(mark)); memset(cost,0,sizeof(cost));
        memset(dp,0,sizeof(dp));  memset(f,0,sizeof(f));
        sign=0; tt=0;
        for(i=0;i<=N+1;i++)  s[i].clear();
        for(i=1;i<=N-1;i++)
        {
            scanf("%d%d%d",&a,&b,&t);
            s[a].push_back(b);
            s[b].push_back(a);
            cost[a][b]=cost[b][a]=t;
        }
        for(i=1;i<=N;i++)  scanf("%d",&w[i]);
        Findroute(1,-1);
        if( tt > T)
        {
            printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!\n");
            continue;
        }
        int MAX=T-tt;
        for(i=1;i<=N;i++)
            if( mark[i] )
                dfs(i,-1,MAX);   //对路上的每个点树形dp一次
        for(i=0;i<=MAX;i++) f[1][i]=dp[1][i];
        int pre=1;
        for(i=2;i<=N;i++)          // 对路上的点按次序再dp一次
        {
            if( mark[i] )
            {
                for(j=MAX;j>=0;j--)
                    for(k=0;k<=j;k++)
                    {
                        f[i][j]=max( f[pre][j-k]+dp[i][k],f[i][j]);
                    }
                pre=i;
            }
        }
        printf("%d\n",f[pre][MAX]);
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值