http://blog.csdn.net/libin56842/article/details/9876503
这道题和poj 1155的区别是:
poj1155是边的价值,所以从边的关系入手
hdu1011是点的价值,从点的关系入手,所以node没有val,在dp时不用记录叶子节点个数,只需要对每个点用背包遍历一遍即可
dp[root][j+k] = max(dp[root][j+k],dp[p][k]+dp[root][j])
dp表示在i点放j人能得到的能量
#include <iostream> #include <string> #include <cstring> #include <cstdlib> #include <cstdio> #include <cmath> #include <algorithm> #include <stack> #include <queue> #include <cctype> #include <vector> #include <iterator> #include <set> #include <map> #include <sstream> using namespace std; #define mem(a,b) memset(a,b,sizeof(a)) #define pf printf #define sf scanf #define spf sprintf #define pb push_back #define debug printf("! ") #define MAXN 1010 #define MAX(a,b) a>b?a:b #define blank pf(" ") #define LL long long #define ALL(x) x.begin(),x.end() #define INS(x) inserter(x,x.begin()) #define pqueue priority_queue #define INF 0x3f3f3f3f int n,m; struct node { int y,next; }tree[1050]; int head[105],dp[105][105],ptr=1; int bug[105],vl[105],vis[105]; void add(int x,int y) { tree[ptr].y = y; tree[ptr].next = head[x]; head[x] = ptr++; } void dfs(int root) { int i,j,k; vis[root] = 1; int cost = (bug[root]+19)/20; for(i=cost;i<=m;i++) dp[root][i] = vl[root]; for(i=head[root]; i!=-1; i=tree[i].next) { int p = tree[i].y; if(!vis[p]) { dfs(p); for(j=m;j>=cost;j--) { for(k=1;j+k<=m;k++) { dp[root][j+k] = max(dp[root][j+k],dp[p][k]+dp[root][j]); } } } } } int main() { int i,j,k,a,b; while(~sf("%d%d",&n,&m) && m+n>0) { mem(head,-1); ptr = 1; for(i=1;i<=n;i++) { sf("%d%d",&bug[i],&vl[i]); } for(i=2;i<=n;i++) { sf("%d%d",&a,&b); add(a,b); add(b,a); } if(!m) { pf("0 "); continue; } mem(dp,0); mem(vis,0); dfs(1); pf("%d ",dp[1][m]); } return 0; } /* 5 10 50 10 40 10 40 20 65 30 70 30 1 2 1 3 2 4 2 5 1 1 20 7 -1 -1 */