【HDU1561】The more, The Better | Tree-like backpack, tree-like dp

Main idea:

ACboy likes to play a strategy game. On a map, there are N castles, and each castle has certain treasures. In each game, ACboy allows to conquer M castles and obtain the treasures inside. However, due to geographical reasons, some castles cannot be directly conquered. To conquer these castles, you must first conquer other specific castles. Can you help ACboy figure out which M castles should be conquered to get as many treasures as possible?

Question idea:

This type of tree dp is more obvious

Consider that dp[u][k] represents the maximum value of k items selected from node u, because there is a dependency;

So pay attention to the state transition, pay special attention to the illegal state dp[u][0] not to be included in the transition

Since the whole picture is a forest, run all the trees and rely on the backpack

Run the grouping backpack for the forest in the whole picture

Code:

/*** keep hungry and calm CoolGuang!  ***/
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define d(x) printf("%lld\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e17;
const ll maxn = 2e5+700;
const int mod= 1e9+7;
const int up = 1e9;
template<typename T>inline void read(T &a){char c=getchar();T x=0,f=1;while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
vector<int>v[maxn];
ll dp[2005][2005];
int num[maxn],in[maxn];
ll dpc[2005];
void dfs(int u){
    dp[u][1] = num[u];
    for(int e:v[u]){
        dfs(e);
        for(int k=m;k>=1;k--)
            for(int j=1;j<=k-1;j++)
                dp[u][k] = max(dp[u][k],dp[u][k-j]+dp[e][j]);
    }
}
int main(){
    while(~scanf("%lld%lld",&n,&m)&&n&&m){
        for(int i=1;i<=n;i++) in[i] = 0,v[i].clear();
        for(int i=1;i<=n;i++){
            int x;read(x);read(num[i]);
            if(x) v[x].push_back(i),in[i]++;
        }
        for(int i=1;i<=n;i++)
            for(int k=0;k<=m;k++)
                dp[i][k] = 0;
        for(int i=1;i<=n;i++)
            if(!in[i])
                dfs(i);
        for(int i=0;i<=m;i++) dpc[i] = 0;
        for(int i=1;i<=n;i++){
            if(!in[i]){
                for(int k=m;k>=0;k--){
                    for(int j=0;j<=k;j++){
                        dpc[k] = max(dpc[k],dpc[k-j] + dp[i][j]);
                    }
                }
            }
        }
        ll ans = 0;
        for(int i=0;i<=m;i++) ans = max(ans,dpc[i]);
        printf("%lld\n",ans);
    }
    return 0;
}

/***
4 3
0 0
1 0
2 0
3 1
****/

 

Guess you like

Origin blog.csdn.net/qq_43857314/article/details/111314289