BZOJ2427: [HAOI2010]软件安装
Posted ~Silent
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ2427: [HAOI2010]软件安装相关的知识,希望对你有一定的参考价值。
题目大意:
软件之间有依赖关系,若这款软件依赖的软件能产生贡献且这款软件被安装了则这款软件能产生vi的贡献,同时安装这款软件需要wi的内存。
问内存不超过m时所能得到的最大贡献。
题解:
若依赖关系存在环,显然要使得环中的任意一个软件产生贡献必须把整个环取了。
先缩点,把一个环当成一个物品,然后缩完点的图就是一棵树。
树上一个点被取了,他的父亲也必须被取。
做一遍背包就好了。
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,m,id,ti,cnt,top,in[1000005],x[1000005],f[505][505],last[1000005],dfn[1000005],low[1000005],stack[1000005],instack[1000005],belong[1000005],sw[1000005],sv[1000005],v[1000005],w[1000005]; struct node{ int to,next; }e[1000005]; void add(int a,int b){ e[++cnt].to=b; e[cnt].next=last[a]; last[a]=cnt; } void Tarjan(int x,int fa){ dfn[x]=low[x]=++ti; stack[++top]=x; instack[x]=1; for (int i=last[x]; i; i=e[i].next){ int V=e[i].to; if (!dfn[V]){ Tarjan(V,x); low[x]=min(low[x],low[V]); } else if (instack[V]) low[x]=min(low[x],dfn[V]); } if (low[x]==dfn[x]){ id++; int now=0; while (now!=x){ now=stack[top--]; instack[now]=0; belong[now]=id; sv[id]+=v[now]; sw[id]+=w[now]; } } } void dp(int x){ for (int i=last[x]; i; i=e[i].next){ int V=e[i].to; dp(V); for (int j=m-sw[x]; j>=0; j--) for (int k=0; k<=j; k++) f[x][j]=max(f[x][j],f[x][k]+f[V][j-k]); } for (int j=m; j>=0; j--){ if (j>=sw[x]) f[x][j]=f[x][j-sw[x]]+sv[x]; else f[x][j]=0; } } 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; i<=n; i++){ scanf("%d",&x[i]); if (x[i]) add(x[i],i); } for (int i=1; i<=n; i++) if (!dfn[i]) Tarjan(i,0); cnt=0; memset(last,0,sizeof(last)); for (int i=1; i<=n; i++) if (x[i] && belong[x[i]]!=belong[i]){ add(belong[x[i]],belong[i]); in[belong[i]]++; } for (int i=1; i<=id; i++) if (!in[i]) { add(id+1,i); } dp(id+1); printf("%d\n",f[id+1][m]); return 0; }
以上是关于BZOJ2427: [HAOI2010]软件安装的主要内容,如果未能解决你的问题,请参考以下文章
[BZOJ2427][HAOI2010]软件安装(Tarjan+DP)