题目描述:
QAQ…
题目分析:
有依赖性关系的背包问题称为树形依赖背包…
用树形动归的方法解决
转移方程并不难
dp[i][j]表示以i为根的子树背包容量为j所能达到的最大价值
实际操作中我们可以用一个虚根来链接没有依赖的点…
这样的转移是
的
听说黑科技可以做到
for(int i=w[now];i<=m;i++) dp[now][i]=val[now];
for(int i=head[now];i;i=net[i])
{
dfs(to[i]);
for(int j=m-w[now];j>=0;j--)
for(int k=0;k<=j;k++)
dp[now][j+w[now]]=std::max(dp[now][j+w[now]],dp[now][j+w[now]-k]+dp[to[i]][k]);
}
要注意一个问题,当依赖关系形成环的时候,我们只能将环内的点全部选了,或者是全部不选,所以需要用Tarjan先缩一下点…
题目链接:
Ac 代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
const int maxm=1001;
int dp[maxm][501],d[maxm];
int dfn[maxm],low[maxm],vis[maxm],c[maxm],stk[maxm],num,col,top;
int W[maxm],Val[maxm],val[maxm],w[maxm],fa[maxm];
int _head[maxm],_to[maxm<<1],_net[maxm<<1],_cnt;
int head[maxm],to[maxm<<1],net[maxm<<1],cnt;
int n,m;
inline void addedge(int u,int v)
{
cnt++;
to[cnt]=v,net[cnt]=head[u],head[u]=cnt;
}
inline void _addedge(int u,int v)
{
_cnt++;
_to[_cnt]=v,_net[_cnt]=_head[u],_head[u]=_cnt;
}
void Tarjan(int x)
{
dfn[x]=low[x]=++num;
stk[++top]=x;
vis[x]=1;
for(int i=_head[x];i;i=_net[i])
{
int p=_to[i];
if(!dfn[p])
{
Tarjan(p);
low[x]=std::min(low[x],low[p]);
}
else if(vis[p]) low[x]=std::min(low[x],dfn[p]);
}
if(low[x]==dfn[x])
{
col++;
while(stk[top]!=x)
{
c[stk[top]]=col;
vis[stk[top--]]=0;
}
c[x]=col,vis[x]=0;
top--;
}
}
void dfs(int now)
{
for(int i=w[now];i<=m;i++) dp[now][i]=val[now];
for(int i=head[now];i;i=net[i])
{
dfs(to[i]);
for(int j=m-w[now];j>=0;j--)
for(int k=0;k<=j;k++)
dp[now][j+w[now]]=std::max(dp[now][j+w[now]],dp[now][j+w[now]-k]+dp[to[i]][k]);
}
}
int main()
{
//freopen("install.in","r",stdin);
//freopen("install.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&W[i]);
for(int i=1;i<=n;i++)
scanf("%d",&Val[i]);
for(int i=1,x;i<=n;i++)
{
scanf("%d",&fa[i]);
if(fa[i]) _addedge(fa[i],i);
}
for(int i=1;i<=n;i++) if(!dfn[i]) Tarjan(i);
for(int i=1;i<=n;i++)
{
if(c[i]!=c[fa[i]]) addedge(c[fa[i]],c[i]),d[c[i]]++;
w[c[i]]+=W[i];
val[c[i]]+=Val[i];
}
for(int i=1;i<=col;i++) if(!d[i]) addedge(0,i);
dfs(0);
printf("%d\n",dp[0][m]);
return 0;
}