2427: [HAOI2010]软件安装
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2043 Solved: 817
[ Submit][ Status][ Discuss]
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
3 10
5 5 6
2 3 4
0 1 1
5 5 6
2 3 4
0 1 1
Sample Output
5
#include<iostream> #include<cstdio> #include<cstring> #define maxn 2010 using namespace std; int n,m,w[maxn],v[maxn],ww[maxn],vv[maxn],head1[maxn],num1,head[maxn],num,root; int dfn[maxn],low[maxn],st[maxn],top,cnt,group,belong[maxn],chu[maxn],ru[maxn],f[maxn][maxn]; bool in[maxn]; struct node{int to,pre;}ee[maxn*10],e[maxn*10]; void Insert1(int from,int to){ ee[++num1].to=to; ee[num1].pre=head1[from]; head1[from]=num1; } void Insert(int from,int to){ e[++num].to=to; e[num].pre=head[from]; head[from]=num; } void Tarjan(int u){ dfn[u]=low[u]=++cnt; st[++top]=u;in[u]=1; for(int i=head1[u];i;i=ee[i].pre){ int v1=ee[i].to; if(!dfn[v1]){ Tarjan(v1); low[u]=min(low[u],low[v1]); } else if(in[v1]) low[u]=min(low[u],dfn[v1]); } if(dfn[u]==low[u]){ group++; while(st[top]!=u){ int x=st[top];top--; in[x]=0; belong[x]=group; w[group]+=ww[x]; v[group]+=vv[x]; } top--;in[u]=0; belong[u]=group; w[group]+=ww[u]; v[group]+=vv[u]; } } void dfs(int x){ if(chu[x]==0){ for(int i=m;i>=w[x];i--)f[x][i]=v[x]; return; } for(int i=head[x];i;i=e[i].pre){ int to=e[i].to; dfs(to); } for(int i=head[x];i;i=e[i].pre){ int to=e[i].to; for(int j=m;j>=0;j--) for(int k=j;k>=0;k--) f[x][j]=max(f[x][j],f[x][j-k]+f[to][k]); } for(int i=m;i>=0;i--){ 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); int x; for(int i=1;i<=n;i++)scanf("%d",&ww[i]); for(int i=1;i<=n;i++)scanf("%d",&vv[i]); for(int i=1;i<=n;i++){ scanf("%d",&x); if(x)Insert1(x,i); } for(int i=1;i<=n;i++) if(!dfn[i])Tarjan(i); for(int i=1;i<=n;i++) for(int j=head1[i];j;j=ee[j].pre){ int to=ee[j].to; if(belong[to]!=belong[i]){ Insert(belong[i],belong[to]); chu[belong[i]]++;ru[belong[to]]++; } } for(int i=1;i<=group;i++) if(ru[i]==0)Insert(root,i),chu[root]++; dfs(root); cout<<f[root][m]; return 0; }