您的位置:首页 > 其它

hdu 4276 树形DP

2013-08-09 10:16 274 查看
这题看了点别人的思路。

先是用一次广搜,搜出从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
== -1 || ( edge[head
].to == pre && edge[head
].next == -1 ) ){
for( int i = 0; i <= T; i++ ){
dp
[i] = value
;
}
return;
}

for( int i = head
; 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
[j] = max( dp
[j], dp
[j-k-2*edge[i].length] + dp[t][k] );
}
}
}
for( int i = 0; i <= T; i++ ){
dp
[i] += value
;
}
}

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: