HDU 4276 树形dp

The Ghost Blows Light

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3452    Accepted Submission(s): 1086


Problem Description

My name is Hu Bayi, robing an ancient tomb in Tibet. The tomb consists of N rooms (numbered from 1 to N) which are connected by some roads (pass each road should cost some time). There is exactly one route between any two rooms, and each room contains some treasures. Now I am located at the 1st room and the exit is located at the Nth room. 
Suddenly, alert occurred! The tomb will topple down in T minutes, and I should reach exit room in T minutes. Human beings die in pursuit of wealth, and birds die in pursuit of food! Although it is life-threatening time, I also want to get treasure out as much as possible. Now I wonder the maximum number of treasures I can take out in T minutes.
 

 

Input
There are multiple test cases.
The first line contains two integer N and T. (1 <= n <= 100, 0 <= T <= 500)
Each of the next N - 1 lines contains three integers a, b, and t indicating there is a road between a and b which costs t minutes. (1<=a<=n, 1<=b<=n, a!=b, 0 <= t <= 100)
The last line contains N integers, which Ai indicating the number of treasure in the ith room. (0 <= Ai <= 100)
 

 

Output
For each test case, output an integer indicating the maximum number of treasures I can take out in T minutes; if I cannot get out of the tomb, please output "Human beings die in pursuit of wealth, and birds die in pursuit of food!".
 

 

Sample Input
5 10
1 2 2
2 3 2
2 5 3
3 4 3
1 2 3 4 5
 

 

Sample Output
11
 

 

Source
 题意:
n个点n-1条无向边的树,通过每条边有时间,每个点有权值,要求在T时间内从1点走到n点得到的最大价值(每点的价值只算一次)
代码:
//1~n点的路径是必须走的并且只走一次,先dfs处理出这条路径并把路径的边权值设为0
//然后顺着这条路径从下到上进行树形dp即可(其他的边如果经过就要走两次)
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1009;
int flag,sum,n,T,dp[maxn][509],head[maxn],tol,val[maxn],pre[maxn];
struct Edge{
    int to,w,next;
}edge[maxn*2];
void Add(int x,int y,int z){
    edge[tol].to=y;
    edge[tol].w=z;
    edge[tol].next=head[x];
    head[x]=tol++;
}
void dfs1(int x,int fa,int cnt){
    pre[x]=fa;
    if(x==n){
        flag=1;
        T-=cnt;
        return;
    }
    for(int i=head[x];i!=-1;i=edge[i].next){
        int y=edge[i].to;
        if(y==fa) continue;
        dfs1(y,x,edge[i].w+cnt);
        if(flag){
            edge[i].w=0;
            return;
        }
    }
}
void dfs2(int x,int fa){
    for(int i=0;i<=T;i++) dp[x][i]=val[x];
    for(int i=head[x];i!=-1;i=edge[i].next){
        int y=edge[i].to;
        if(y==fa) continue;
        dfs2(y,x);
        for(int j=T;j>=2*edge[i].w;j--){
            for(int k=0;k+2*edge[i].w<=j;k++){
                dp[x][j]=max(dp[x][j],dp[x][j-2*edge[i].w-k]+dp[y][k]);
            }
        }
    }
}
void solve(int x){
    sum=0;
    while(x!=0){
        sum+=val[x];
        val[x]=0;
        dfs2(x,pre[x]);
        x=pre[x];
    }
    
}
int main()
{
    while(scanf("%d%d",&n,&T)==2){
        memset(head,-1,sizeof(head));
        tol=0;
        memset(pre,0,sizeof(pre));
        for(int i=1;i<n;i++){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            Add(x,y,z);Add(y,x,z);
        }
        for(int i=1;i<=n;i++) scanf("%d",&val[i]);
        flag=0;
        dfs1(1,0,0);
        if(T<0){
            printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!\n");
            continue;
        }
        memset(dp,0,sizeof(dp));
        solve(n);
        printf("%d\n",sum+dp[1][T]);
    }
    return 0;
}

 

 

posted @ 2017-05-18 11:30  luckilzy  阅读(313)  评论(0编辑  收藏  举报