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;
}
View Code
没有人不辛苦,只有人不喊疼
原文地址:https://www.cnblogs.com/ctyakwf/p/14706165.html