[树形DP][背包]luogu P2515 软件安装
https://www.luogu.org/problemnew/show/P2515
分析
沙雕题*2
这题就是随便做个树形背包,Tarjan缩点把价值和体积加起来而已
注意必须保留当前节点的价值和体积
#include <iostream> #include <cstdio> #include <memory.h> using namespace std; const int N=110; const int M=510; struct Graph { int u,v,nx; }g[N*N]; int cnt,list[N],deg[N]; int low[N],dfn[N],tme; int stk[N],top; bool instk[N]; int w[N],v[N],idw[N],idv[N],id[N],idcnt; int n,m,rt; int f[N][M]; void Add(int u,int v) { g[++cnt]=(Graph){u,v,list[u]};list[u]=cnt; } void Tarjan(int u) { dfn[u]=low[u]=++tme; stk[++top]=u;instk[u]=1; for (int i=list[u];i;i=g[i].nx) if (!dfn[g[i].v]) { Tarjan(g[i].v); low[u]=min(low[u],low[g[i].v]); } else if (instk[g[i].v]) low[u]=min(low[u],dfn[g[i].v]); if (low[u]==dfn[u]) { idcnt++; do { id[stk[top]]=idcnt;idw[idcnt]+=w[stk[top]];idv[idcnt]+=v[stk[top]]; instk[stk[top]]=0; } while (stk[top--]!=u); } } void DFS(int u) { if (idw[u]<=m) f[u][idw[u]]=idv[u]; for (int i=idw[u]+1;i<=m;i++) f[u][i]=f[u][i-1]; for (int i=list[u];i;i=g[i].nx) { DFS(g[i].v); for (int j=m;j>=idw[u];j--) for (int k=idw[g[i].v];k<=j-idw[u];k++) f[u][j]=max(f[u][j],f[u][j-k]+f[g[i].v][k]); } } int main() { 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",&v[i]); for (int i=1,f;i<=n;i++) { scanf("%d",&f); if (f) Add(f,i); } for (int i=1;i<=n;i++) if (!dfn[i]) Tarjan(i); memset(list,0,sizeof list);cnt=0; for (int i=1;i<=m;i++) if (id[g[i].u]!=id[g[i].v]) deg[id[g[i].v]]++,Add(id[g[i].u],id[g[i].v]); for (int i=1;i<=idcnt;i++) if (!deg[i]) Add(0,i); DFS(0); printf("%d",f[0][m]); }
在日渐沉没的世界里,我发现了你。