hdu1011(树形dp+背包)
src:http://acm.hdu.edu.cn/showproblem.php?pid=1011
dp[u][i]表示在结点u,消耗i军队获得的最大值。注意建树时用双向边,因为结点1不一定是树根!!!
注意m==0时特判,这个必需要,有代价为0的房间,M=0则无法获得,样例为2 0 0 20 0 10 1 2 !!!
ac代码:
#include <iostream> #include<cstdlib> #include<algorithm> #include<cmath> #include<functional> #include<utility> #include<string> #include<string.h> #include<vector> #include<iomanip> #include<stack> using namespace std; #define FOR(i,a,b) for(int i=a;i<=b;i++) #define Max(a,b) a=max(a,b) #define Min(a,b) a=min(a,b) const int inf=99999999; int n,m,dp[101][101],b[101],g[101]; bool vis[101]; vector<int>head[101]; void init() { memset(dp,0,sizeof(dp)); memset(vis,false,sizeof(vis)); FOR(i,1,n)head[i].clear(); } void add_edge(int beg,int ed){head[beg].push_back(ed);} void dfs(int u) { vis[u]=true; for(int i=b[u];i<=m;i++)dp[u][i]=g[u]; for(int i=0;i<head[u].size();i++){ int v=head[u][i]; if(vis[v]==true)continue; dfs(v); for(int j=m;j>=b[u];j--)for(int k=1;k<=j-b[u];k++){ Max(dp[u][j],dp[u][j-k]+dp[v][k]); } } } int main() { ios::sync_with_stdio(false); while(cin>>n>>m&&n!=-1&&m!=-1){ int beg,ed; init(); for(int i=1;i<=n;i++){cin>>b[i]>>g[i];} for(int i=1;i<=n;i++)b[i]=(b[i]+19)/20; for(int i=1;i<n;i++){cin>>beg>>ed;add_edge(beg,ed);add_edge(ed,beg);} if(!m){ //注意m==0时特判 cout<<"0"<<endl;continue; } dfs(1); cout<<dp[1][m]<<endl; } return 0; }

浙公网安备 33010602011771号