[树形dp]蓝桥杯-生产车间
#include <bits/stdc++.h>
#define ll long long
#define pll pair<int,int>
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
const int N=1e6+7;
const int mod=1e9+7;
void solve(){
int n;
cin>>n;
vector<int>w(n+3);
for(int i=1;i<=n;i++)
{
cin>>w[i];
}
vector<int>g[N];
for(int i=1;i<=n-1;i++)
{
int u,v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
vector<vector<bool>>dp(n+3,vector<bool>(1003,false));
auto dfs=[&](auto &&self,int u,int fa)->void
{
if(g[u].size()==1 && g[u][0]==fa)
{
dp[u][w[u]]=1;
return;
}
dp[u][0]=1;
for(auto v:g[u])
{
if(v==fa)continue;
self(self,v,u);
for(int i=w[u];i>=0;i--)
{
for(int j=0;j<=w[v] && j<=i;j++)
{
if(dp[u][i]==1)continue;
else dp[u][i]=dp[u][i-j]&dp[v][j];
}
}
}
return;
};
dfs(dfs,1,-1);
int ans=0;
for(int i=1;i<=1000;i++)
{
if(dp[1][i])ans=max(ans,i);
}
cout<<ans<<endl;
return ;
}
signed main (){
IOS;
int _=1;
//cin>>_;
while(_--){
solve();
}
return 0;
}
/*
*/
分析:一棵树,只有叶子节点才有价值,其余每个节点的值为当前背包的容积,求最高价值。
每个节点可能有多个值,但只选一个,可以看出是分组背包。
dp[u][i]=dp[u][i] || (dp[u][i-j]&dp[v][j]);
浙公网安备 33010602011771号