这题看了点别人的思路。
先是用一次广搜,搜出从1到N的最短路径,判断是否小于T(就是判断下能否逃出去),然后将这条路径上的所有边的权值变成0,这样再进行一次树形DP那么刚刚为0的边一定会选进去,其他的边用DP选。有一点要注意,这时候权值要乘以2,因为要回来。不懂的话,画下图就知道了。
AC代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
typedef struct{
int to;
int next;
int length;
}Edge;
typedef struct{
vector<int> edge;
int time;
int now;
}Node;
Edge edge[202];
int head[101];
int N, T;
int value[101];
int tot;
int dp[101][501];
bool visit[101];
int sum;
inline int max( int a, int b ){
return ( a > b ? a : b );
}
void add_edge( int a, int b, int c ){
edge[tot].to = b;
edge[tot].length = c;
edge[tot].next = head[a];
head[a] = tot++;
edge[tot].to = a;
edge[tot].length = c;
edge[tot].next = head[b];
head[b] = tot++;
}
void BFS(){
bool mark[101];
queue<Node> q;
Node start;
Node end;
start.now = 1;
start.time = 0;
start.edge.clear();
q.push( start );
memset( mark, false, sizeof( mark ) );
mark[1] = true;
while( !q.empty() ){
Node n = q.front();
q.pop();
if( n.now == N ){
end = n;
break;
}
int t = n.now;
for( int i = head[t]; i != -1; i = edge[i].next ){
Node temp = n;
temp.now = edge[i].to;
temp.edge.push_back( i );
temp.time += edge[i].length;
if( mark[temp.now] ){
continue;
}
mark[temp.now] = true;
q.push( temp );
}
}
sum = 0;
for( int i = 0; i < end.edge.size(); i++ ){
sum += edge[end.edge[i]].length;
edge[end.edge[i]].length = 0;
}
}
void DFS( int n, int pre ){
if( head[n] == -1 || ( edge[head[n]].to == pre && edge[head[n]].next == -1 ) ){
for( int i = 0; i <= T; i++ ){
dp[n][i] = value[n];
}
return;
}
for( int i = head[n]; i != -1; i = edge[i].next ){
int t = edge[i].to;
if( visit[t] ){
continue;
}
if( t == pre ){
continue;
}
visit[t] = true;
DFS( t, n );
for( int j = T; j >= 0; j-- ){
for( int k = 0; k + 2 * edge[i].length <= j; k++ ){
dp[n][j] = max( dp[n][j], dp[n][j-k-2*edge[i].length] + dp[t][k] );
}
}
}
for( int i = 0; i <= T; i++ ){
dp[n][i] += value[n];
}
}
int main(){
while( scanf( "%d%d", &N, &T ) != EOF ){
memset( value, 0, sizeof( value ) );
memset( head, -1, sizeof( head ) );
tot = 0;
for( int i = 1; i < N; i++ ){
int temp1, temp2, temp3;
cin >> temp1 >> temp2 >> temp3;
add_edge( temp1, temp2, temp3 );
}
for( int i = 1; i <= N; i++ ){
cin >> value[i];
}
BFS();
if( sum <= T ){
memset( dp, 0, sizeof( dp ) );
memset( visit, 0, sizeof( visit ) );
DFS( 1, 0 );
cout << dp[1][T-sum] << endl;
}else{
cout << "Human beings die in pursuit of wealth, and birds die in pursuit of food!" << endl;
}
}
return 0;
}