Description
现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi。我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大)。
但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j)。幸运的是,一个软件最多依赖另外一个软件。如果一个软件不能正常工作,那么它能够发挥的作用为0。
我们现在知道了软件之间的依赖关系:软件i依赖软件Di。现在请你设计出一种方案,安装价值尽量大的软件。一个软件只能被安装一次,如果一个软件没有依赖则Di=0,这时只要这个软件安装了,它就能正常工作。
Input
第1行:N, M (0<=N<=100, 0<=M<=500)
第2行:W1, W2, ... Wi, ..., Wn (0<=Wi<=M )
第3行:V1, V2, ..., Vi, ..., Vn (0<=Vi<=1000 )
第4行:D1, D2, ..., Di, ..., Dn (0<=Di<=N, Di≠i )
Output
一个整数,代表最大价值。
Sample Input
5 5 6
2 3 4
0 1 1
Sample Output
#include<cmath> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; struct node{ int x,y,next; }a[21000];int len,last[21000]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } int n,m; int tot[510],dfn[510],low[510]; int belong[510],sta[510]; bool v[510]; int cost[510]; int id,cnt,top; int w[510],c[510]; void dfs(int x) { dfn[x]=low[x]=++id; v[x]=true;sta[++top]=x; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(dfn[y]==-1) { dfs(y); low[x]=min(low[x],low[y]); } else if(v[y]==true) low[x]=min(low[x],dfn[y]); } if(dfn[x]==low[x]) { cnt++;int i; do{ i=sta[top--]; belong[i]=cnt; v[i]=false; cost[cnt]+=w[i]; tot[cnt]+=c[i]; }while(i!=x); } } int d[510]; int ru[510]; int total[510]; int f[510][510]; void treedp(int x) { f[x][cost[x]]=tot[x];total[x]=cost[x]; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; treedp(y); for(int i=m;i>cost[x];i--) for(int j=0;j<=total[y];j++) if(i-j>=0&&i-j>=cost[x])f[x][i]=max(f[x][i],f[y][j]+f[x][i-j]); total[x]+=total[y]; } } int main() { scanf("%d%d",&n,&m); len=0;memset(last,0,sizeof(last)); for(int i=1;i<=n;i++)scanf("%d",&w[i]); for(int i=1;i<=n;i++)scanf("%d",&c[i]); for(int i=1;i<=n;i++) { scanf("%d",&d[i]); if(d[i]!=0)ins(d[i],i); } id=cnt=top=0; memset(dfn,-1,sizeof(dfn)); memset(v,false,sizeof(v)); for(int i=1;i<=n;i++) if(dfn[i]==-1) dfs(i); len=0;memset(last,0,sizeof(last)); for(int i=1;i<=n;i++) if(belong[i]!=belong[d[i]]) ins(belong[d[i]],belong[i]),ru[belong[i]]++; for(int i=1;i<=n;i++) if(ru[i]==0) ins(0,i); treedp(0); printf("%d\n",f[0][m]); return 0; }
by_lmy