The Ghost Blows Light
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1410 Accepted Submission(s): 420
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
Recommend
liuyiding
题目:给出一棵树,从1走到n,总时间为T,每走一条边需要花费一定时间,每个结点有一定价值,问在指定时间内回到T的能获取的最大价值
首先dfs或者spfa求一次最短路,如果从1到n的最短花费都小于总时间,则是不可能。
而且在最短路的时候记录每个节点的父节点,以及边的编号
然后将最短路径上的所有边权置为0.将总时间减去最短路径。
这样处理的目的是,显然最短路上的边只会走一遍才是最优的,而且剩下的边要么不走,要么走两次,而且DFS求一次树形DP之后,不需要考虑回到n的情况,因为1-n的最短路径走了一遍,其它边走0次或两次,肯定是回到n的。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int VM=120; struct Edge{ int to,nxt; int cap; }edge[VM<<1]; int n,T,cnt,head[VM]; int dp[VM][520],val[VM]; //dp[i][j]表示从第i个点开始,回到i点,花费j时间得到的最大财富值 void addedge(int cu,int cv,int cw){ edge[cnt].to=cv; edge[cnt].cap=cw; edge[cnt].nxt=head[cu]; head[cu]=cnt++; } int time1; int DFS1(int u,int pre){ //找从1到N的最短时间 if(u==n) return 1; for(int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].to; if(v==pre) continue; if(DFS1(v,u)){ time1+=edge[i].cap; edge[i].cap=0; return 1; } } return 0; } /* void spfa(int s){ queue<int>que; int vis[N]; mem(vis,0);mem(pre,0); for(int i=1;i<=n;i++) if(i==s) dist[i]=0; else dist[i]=inf; que.push(s); vis[s]=1; while(!que.empty()){ int u=que.front(); que.pop(); vis[u]=0; for(int i=start[u];i!=-1;i=edge[i].next){ int v=edge[i].v,w=edge[i].w; if(dist[v]>dist[u]+w){ dist[v]=dist[u]+w; pre[v]=u; p[v]=i; if(!vis[v]){ vis[v]=1; que.push(v); } } } } for(int i=n;i!=1;i=pre[i]){ edge[p[i]].w=0; edge[p[i]^1].w=0; } } */ void DFS2(int u,int pre){ for(int i=0;i<=T;i++) dp[u][i]=val[u]; for(int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].to; if(v==pre) continue; DFS2(v,u); int cost=edge[i].cap*2; //要走两遍 for(int j=T;j>=cost;j--) for(int k=0;k<=j-cost;k++) dp[u][j]=max(dp[u][j],dp[v][k]+dp[u][j-cost-k]); } } int main(){ //freopen("input.txt","r",stdin); while(~scanf("%d%d",&n,&T)){ cnt=0; memset(head,-1,sizeof(head)); int u,v,w; for(int i=1;i<n;i++){ scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); } for(int i=1;i<=n;i++) scanf("%d",&val[i]); time1=0; DFS1(1,-1); if(T<time1){ printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!\n"); continue; } T-=time1; DFS2(1,-1); printf("%d\n",dp[1][T]); } return 0; }