[填坑][支线任务]树形DP 树形背包
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[填坑][支线任务]树形DP 树形背包相关的知识,希望对你有一定的参考价值。
开启了树包支线任务QAQ
我还是弱啊==
[树形背包]BZOJ 2427 软件安装
这道题原来考过,大概是半年前了,然而现在再回来填坑,却发现还是会的不透彻,颓了颓原来自己的代码T-T
这就是有依赖的背包问题,可以看做分组背包,但是会有很多冗杂的状态,所以我们要对依赖它的“附件”进行一次01背包,把它们泛化
然后我们要把“主件”选上(因为必须要有它),和泛化后的“附件”新组合成物品。当然它也可以单独存在,不选任何“附件”。
当然这道题有坑点:可能有依赖环出现,所以我们要Tarjan缩一下点(最开始一直WA竟然是因为Tarjan打错了,悲伤==)
update:因为是一片森林,所以我们要建一个超级源点233
#include<iostream> #include<cstdio> #include<cstdio> #define pos(i,a,b) for(int i=(a);i<=(b);i++) #define pos2(i,a,b) for(int i=(a);i>=(b);i--) #define N 2011 #define LL long long using namespace std; struct haha{ int next,to; }edge[N*10],edgechu[N*10]; int head[N],cnt=1,headchu[N],cntchu=1; void add(int u,int v){ edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt++; } void addchu(int u,int v){ edgechu[cntchu].to=v; edgechu[cntchu].next=headchu[u]; headchu[u]=cntchu++; } int n,m,in[N],wchu[N],vchu[N]; int dfn[N],ji,low[N],hea,instack[N],stack[N]; int cntt,v[N],w[N],belong[N]; void tarjan(int x){ dfn[x]=low[x]=++ji; instack[x]=1;stack[++hea]=x; for(int i=headchu[x];i;i=edgechu[i].next){ int to=edgechu[i].to; if(dfn[to]==-1){ tarjan(to); low[x]=min(low[x],low[to]); } else if(instack[to]) low[x]=min(low[x],dfn[to]); } if(low[x]==dfn[x]){ int temp; cntt++; while(1){ temp=stack[hea--]; instack[temp]=0; w[cntt]+=wchu[temp]; v[cntt]+=vchu[temp]; belong[temp]=cntt; if(temp==x) break; } } } int f[N][N],root,out[N]; void dfs(int x){ if(out[x]==0){ pos2(i,m,w[x]) f[x][i]=v[x]; return; } for(int i=head[x];i;i=edge[i].next){ int to=edge[i].to; dfs(to); } for(int i=head[x];i;i=edge[i].next){ int to=edge[i].to; pos2(j,m,0){ pos2(k,j,0){ f[x][j]=max(f[x][j],f[x][j-k]+f[to][k]); } } } pos2(i,m,0){ if(i>=w[x]) f[x][i]=f[x][i-w[x]]+v[x]; else f[x][i]=0; } } int main(){ scanf("%d%d",&n,&m); pos(i,1,n) scanf("%d",&wchu[i]); pos(i,1,n) scanf("%d",&vchu[i]); pos(i,1,n){ int x;scanf("%d",&x); if(x) addchu(x,i); } pos(i,0,n) dfn[i]=-1; pos(i,1,n) if(dfn[i]==-1) tarjan(i); pos(x,1,n){ for(int i=headchu[x];i;i=edgechu[i].next){ int to=edgechu[i].to; if(belong[to]!=belong[x]){ add(belong[x],belong[to]);out[belong[x]]++;in[belong[to]]++; } } } root=0; pos(i,1,cntt){ if(in[i]==0){ add(root,i);out[root]++; } } dfs(root); cout<<f[root][m]; return 0; }
以上是关于[填坑][支线任务]树形DP 树形背包的主要内容,如果未能解决你的问题,请参考以下文章
HDU-1011 Starship Troopers (树形DP+分组背包)