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)
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! "); continue; } memset(dp,0,sizeof(dp)); solve(n); printf("%d ",sum+dp[1][T]); } return 0; }