The Ghost Blows Light
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4276
题意:
在一个n个节点的树形迷宫中,1为起点,n为出口。每个节点上有一定价值的珠宝,在节点之间移动的时间已知,问在能走出迷宫的前提下并且不超过m的时间内能收集的最多珠宝是多少?
思路:
我们首先考虑直接从1->n走的路径是必须要走的,我们先统计出这个的价值和时间。
如果时间允许的话,那么除这些路径以外的所有路径都是需要走两遍的,这就像之前一道题允许重复走所获的的最大价值一样了
f[u][j] u为根结点时间为j的时候允许获得的最大价值
转移方程:
f[u][j] = max(f[u][j],f[u][j-k]+f[v][k-2*w] ) (w是 u->v 的边权)
#include <iostream> #include <algorithm> #include <string> #include <string.h> #include <vector> #include <map> #include <stack> #include <set> #include <queue> #include <math.h> #include <cstdio> #include <iomanip> #include <time.h> #include <bitset> #include <cmath> #include <sstream> #define LL long long #define INF 0x3f3f3f3f #define ls nod<<1 #define rs (nod<<1)+1 const double eps = 1e-10; const int maxn = 100 + 10; const LL mod = 1e9 + 7; int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;} using namespace std; struct edge { int v,w,nxt; }e[maxn<<1]; int head[maxn]; int f[maxn][510],w[maxn]; int cnt; int n,m,sum; inline void add_edge(int u,int v,int w) { e[++cnt].v = v; e[cnt].w = w; e[cnt].nxt = head[u]; head[u] = cnt; } inline bool get_sum(int x,int fa) { if (x == n) return true; for (int i = head[x];~i;i = e[i].nxt) { int v = e[i].v; if (v == fa) continue; if (get_sum(v,x)) { sum += e[i].w; e[i].w = 0; return true; } } return false; } inline void dfs(int x,int fa) { for (int i = head[x];~i;i = e[i].nxt) { int v = e[i].v; if (v == fa) continue; dfs(v,x); for (int j = m;j >= 0;j--) { for (int k = 2*e[i].w;k <= j;k++) f[x][j] = max(f[x][j],f[x][j-k]+f[v][k-2*e[i].w]); } } } int main() { while (cin >> n >> m) { sum = 0; cnt = 0; memset(f,0, sizeof(f)); memset(head,-1, sizeof(head)); for (int i = 1;i < n;i++) { int a,b,c; cin >> a >> b >> c; add_edge(a,b,c); add_edge(b,a,c); } for (int i = 1;i <= n;i++) cin >> w[i]; for (int i = 1;i <= n;i++) { for (int j = 0;j <= m;j++) f[i][j] = w[i]; } get_sum(1,0); m -= sum; if (m < 0) { cout << "Human beings die in pursuit of wealth, and birds die in pursuit of food!" << endl; continue; } dfs(1,0); cout << f[1][m] << endl; } return 0; }