HDU156 The more, The Better(dp+背包)
显然,根据题目给定的数据,结果是一些森林
对于每个森林都可以取一些数使得答案最大
又因为必须到根都取掉,我们设计状态为f[i][j],表示以i为根,取j个的答案
对于树上跑一个01背包,然后对于整个森林跑一下分组背包
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=2e5+10; const int mod=998244353; int n,m; int in[N]; ll a[N]; int h[N],ne[N],e[N],idx; ll f[220][220]; ll dp[220]; int sz[N]; struct node{ ll a,b; }; vector<node> s[220]; void add(int a,int b){ e[idx]=b,ne[idx]=h[a],h[a]=idx++; } void dfs(int u,int fa){ int i; f[u][1]=a[u]; sz[u]=1; for(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==fa) continue; dfs(j,u); for(int l=m;l>=1;l--){ for(int r=1;r<=l-1;r++){ f[u][l]=max(f[u][l],f[u][l-r]+f[j][r]); } } } } int main(){ ios::sync_with_stdio(false); while(cin>>n>>m){ if(n==0&&m==0) break; int i,j; idx=0; for(i=0;i<=2*n;i++){ h[i]=-1; in[i]=0; } for(i=1;i<=n;i++){ ll x,y; cin>>x>>y; a[i]=y; if(x){ add(x,i); in[i]++; } } for(i=0;i<=n;i++){ for(j=0;j<=m;j++){ f[i][j]=0; } } int cnt=0; memset(dp,0,sizeof dp); for(i=1;i<=n;i++){ if(!in[i]){ dfs(i,0); } } for(i=1;i<=n;i++){ if(in[i]) continue; for(j=m;j>=0;j--){ for(int k=0;k<=j;k++){ dp[j]=max(dp[j],dp[j-k]+f[i][k]); } } } cout<<dp[m]<<endl; } return 0; }
没有人不辛苦,只有人不喊疼