首页 > 代码库 > HDU4276 The Ghost Blows Light 树形DP

HDU4276 The Ghost Blows Light 树形DP

做这个题的时候想到了,先来一遍最短路,判断是否可以到达,若可以减去最短路的花费,再在剩下的花费里进行DP求最优解,想到了但是没做到,很多细节没有处理好,结果崩盘了,唉,看题解很多人都是两边dfs,不过这位大牛也是先spfa了一遍,  给我这个弱菜看看 刚好,这篇好好记录下来,


最后参考了大牛的:http://blog.csdn.net/acm_cxlove/article/details/7964739,可以说是一模一样了


#include<iostream>
#include<cstdio>
#include<list>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<cmath>
#include<memory.h>
#include<set>
#include<cctype>

#define ll long long

#define LL __int64

#define eps 1e-8

#define inf 0xfffffff

//const LL INF = 1LL<<61;

using namespace std;

//vector<pair<int,int> > G;
//typedef pair<int,int > P;
//vector<pair<int,int> > ::iterator iter;
//
//map<ll,int >mp;
//map<ll,int >::iterator p;

typedef struct Node {
	int fro,to;
	int nex;
	int val;
};

Node edge[100 * 4];

int value[100 + 5];
int head[100 + 5];
bool vis[100 + 5];
int dis[100 + 5];
int father[100 + 5];
int mark[100 + 5];
int dp[100 + 5][500 + 5];

int tot;

int n,t;

void init() {
	memset(head,-1,sizeof(head));
	memset(value,0,sizeof(value));
	memset(edge,0,sizeof(edge));
	memset(mark,0,sizeof(mark));
	memset(dp,0,sizeof(dp));
	tot = 0;
}

void add(int u,int v,int w) {
	edge[tot].fro = u;
	edge[tot].to = v;
	edge[tot].val = w;
	edge[tot].nex = head[u];
	head[u] = tot++;
}

void spfa() {
	for(int i=0;i<=n;i++)
		dis[i] = inf;
	dis[1] = 0;
	memset(vis,false,sizeof(vis));
	memset(father,0,sizeof(father));
	queue<int> q;
	int s = 1;
	q.push(s);
	vis[s] = true;
	while(!q.empty()) {
		int u = q.front();
		q.pop();
		vis[u] = false;
		for(int i = head[u];i != -1;i = edge[i].nex) {
			int v = edge[i].to;
			int val = edge[i].val;
			if(dis[v] > dis[u] + val) {
				dis[v] = dis[u] + val;
				father[v] = u;
				mark[v] = i;
				if(!vis[v]) {
					vis[v] = true;
					q.push(v);
				}
			}
		}
	}
	for(int i=n;i != 1;i=father[i])
		edge[mark[i]].val = 0;
}

void dfs(int u,int fa) {
	for(int i=head[u];i!=-1;i=edge[i].nex) {
		int v = edge[i].to;
		int val = edge[i].val * 2;
		if(v == fa)continue;
		dfs(v,u);
		for(int j=t;j>=val;j--)
			for(int k = j-val;k>=0;k--)
				dp[u][j] = max(dp[u][j],dp[u][k] + dp[v][j - k - val]);
	}
	for(int i=0;i<=t;i++)
		dp[u][i] += value[u];
}

int main() {
	while(scanf("%d %d",&n,&t) == 2) {
		init();
		for(int i = 1;i < n;i++) {
			int u,v,w;
			scanf("%d %d %d",&u,&v,&w);
			add(u,v,w);
			add(v,u,w);
		}
		for(int i = 1;i <= n;i++)
			scanf("%d",&value[i]);
		spfa();
		if(dis[n] > t) {
			puts("Human beings die in pursuit of wealth, and birds die in pursuit of food!");
			continue;
		}
		t -= dis[n];
		dfs(1,0);
		printf("%d\n",dp[1][t]);
	}
	return 0;
}