HDOJ 4276 The Ghost Blows Light(树形DP+背包)

长春网赛倒数第2题

题意:给一颗带权树,树的边权代表通过所需的费用,树中每个节点有一个value,代表财富值,从结点1出发,求在时间T内到达结点n最多能带走的财富。

分析:从1到n有一条必经之路,对这条路上的结点用树形DP求泛型背包,然后对这些点进行分组背包。

View Code
#include <stdio.h>

#include <string.h>

#include <queue>

using namespace std;

#define MAX(a,b) ((a)>(b)?(a):(b))

#define N 101

int n,T,e;

int first[N],next[N<<1],v[N<<1],t[N<<1],val[N];

int dp[N][5*N],ans[5*N];

int d[N],p[N];

bool vis[N];

void init()

{

    e=0;

    memset(first+1,-1,sizeof(first[0])*n);

}

void add(int a,int b,int c)

{

    v[e]=b;

    t[e]=c;

    next[e]=first[a];

    first[a]=e++;

}

void read()

{

    int a,b,c;

    init();

    for(int i=1;i<n;i++)

    {

        scanf("%d%d%d",&a,&b,&c);

        add(a,b,c);

        add(b,a,c);

    }

    for(int i=1;i<=n;i++)   scanf("%d",&val[i]);

}

int spfa()

{

    memset(d+1,0x3f,sizeof(d[0])*n);

    memset(vis+1,0,sizeof(vis[0])*n);

    d[1]=0;

    queue<int>q;

    int a,b;

    q.push(1);

    vis[1]=1;

    while(!q.empty())

    {

        a=q.front(),q.pop();

        if(a==n)    break;

        vis[a]=0;

        for(int i=first[a];~i;i=next[i])

        {

            b=v[i];

            if(d[b]>d[a]+t[i])

            {

                d[b]=d[a]+t[i];

                p[b]=a;

                if(!vis[b]) vis[b]=1,q.push(b);

            }

        }

    }

    return d[n];

}

void dfs(int a,int fa)

{

    dp[a][0]=val[a];

    for(int i=first[a];~i;i=next[i])

    {

        int b=v[i];

        if(b==fa || vis[b]) continue;

        dfs(b,a);

        for(int j=T;j>=0;j--)

        {

            for(int k=0;j-k-2*t[i]>=0;k++)

            {

                dp[a][j]=MAX(dp[a][j],dp[a][j-k-2*t[i]]+dp[b][k]);

            }

        }

    }

}

void solve()

{

    for(int i=1;i<=n;i++)   memset(dp[i],0xc3,sizeof(dp[0][0])*(T+1));

    memset(vis+1,0,sizeof(vis[0])*n);

    p[1]=0;

    for(int b=n;b;b=p[b])   vis[b]=1;

    for(int i=1;i<=n;i++)   if(vis[i])

    {

        dfs(i,0);

    }



    memset(ans,0xc3,sizeof(ans[0])*(T+1));

    ans[0]=0;

    for(int a=n;a;a=p[a])

    {

        for(int j=T;j>=0;j--)

        {

            for(int k=0;k<=j;k++)

            {

                ans[j]=MAX(ans[j],ans[j-k]+dp[a][k]);

            }

        }

    }

    int max=0;

    for(int i=0;i<=T;i++)   max=MAX(max,ans[i]);

    printf("%d\n",max);

}

int main()

{

    while(~scanf("%d%d",&n,&T))

    {

        read();

        T-=spfa();

        if(T<0)   puts("Human beings die in pursuit of wealth, and birds die in pursuit of food!");

        else    solve();

    }

    return 0;

}

你可能感兴趣的:(host)