HDU 4276 The Ghost Blows Light【树形DP】

题意: 一个有 N 个节点的树形的地图,知道了每条变经过所需要的时间,现在给出时间T,问能不能在T时间内从 1

         号节点到 N 节点。每个节点都有相对应的价值,而且每个价值只能被取一次,问如果可以从1 号节点走到 n 号

          节点的话,最多可以取到的最大价值为多少。

分析:先求出从 1 号节点到 n 号节点的最短路,如果花费大于时间 T,则直接输出不符合,

         将最短路上的权值全部赋值为  0, 在总时间 T 上减去 最短路的长度,表示最短路已经走过,对其它点进行树形背包求解,

         需要注意的是如果不是最短路上的边都要走两次,即走过去还要再走回来,

          状态转移方程:
          dp[i][j]=max(dp[i][j],dp[i][k]+dp[i][j-2*val-k])

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define maxn 105
#define max(a,b)(a)>(b)?(a):(b)
#define clr(x)memset(x,0,sizeof(x))
#define INF 0x1f1f1f1f
struct node
{
    int from,to,next,w;
}e[1000000];
int head[maxn];
int tot;
void add(int s,int u,int wi)
{
    e[tot].from=s;
    e[tot].to=u;
    e[tot].w=wi;
    e[tot].next=head[s];
    head[s]=tot++;
}
int d[maxn];
int q[2000000];
int pre[maxn];
int v[maxn];
int n;
void spafa()
{
    clr(v);
    int front,rear;
    front=rear=0;
    q[rear++]=1;
    v[1]=1;
    d[1]=0;
    pre[1]=-1;
    int i,u,k;
    while(front<rear)
    {
        u=q[front++];
        v[u]=0;
        for(i=head[u];i;i=e[i].next)
        {
            k=e[i].to;
            if(d[u]+e[i].w<d[k])
            {
                pre[k]=i;
                d[k]=d[u]+e[i].w;
                if(!v[k])
                {
                    v[k]=1;
                    q[rear++]=k;
                }
            }
        }
    }
    for(u=pre[n];u!=-1;u=pre[e[u].from])
        e[u].w=0;
}
int val[maxn];
int T;
int dp[maxn][505];
void dfs(int r)
{
    int i,j,son,k;
    v[r]=1;
    for(i=0;i<=T;i++)
        dp[r][i]=val[r];
    for(i=head[r];i;i=e[i].next)
    {
        son=e[i].to;
        if(!v[son])
        {
            dfs(son);
            int tt=e[i].w*2;
            for(j=T;j>=tt;j--)
                for(k=j-tt;k>=0;k--)
                    dp[r][j]=max(dp[r][j],dp[r][k]+dp[son][j-tt-k]);
        }
    }
}
int main()
{
    int i;
    while(scanf("%d%d",&n,&T)!=EOF)
    {
        int a,b,c;
        tot=1;
        clr(head);
        for(i=1;i<n;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c);
            add(b,a,c);
        }
        for(i=1;i<=n;i++)
            scanf("%d",&val[i]);
        memset(d,INF,sizeof(d));
        clr(pre);
        spafa();
        if(d[n]>T)
        {
            printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!\n");
            continue;
        }
        clr(v);
        T-=d[n];
        dfs(1);
        printf("%d\n",dp[1][T]);
    }
    return 0;
}

 

posted @ 2012-09-13 20:14  'wind  阅读(578)  评论(0编辑  收藏  举报