现在的位置: 首页 > 综合 > 正文

hdu 4276 树形DP

2013年10月08日 ⁄ 综合 ⁄ 共 2023字 ⁄ 字号 评论关闭

这题看了点别人的思路。

先是用一次广搜,搜出从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;
}

 

抱歉!评论已关闭.