https://www.luogu.org/problem/show?pid=2515#sub
题目描述
现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi。我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大)。
但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j)。幸运的是,一个软件最多依赖另外一个软件。如果一个软件不能正常工作,那么它能够发挥的作用为0。
我们现在知道了软件之间的依赖关系:软件i依赖软件Di。现在请你设计出一种方案,安装价值尽量大的软件。一个软件只能被安装一次,如果一个软件没有依赖则Di=0,这时只要这个软件安装了,它就能正常工作。
输入输出格式
输入格式:
第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 )
输出格式:
一个整数,代表最大价值
输入输出样例
输入样例#1:
3 10 5 5 6 2 3 4 0 1 1
输出样例#1:
5
f[u][i]表示安装u占用i的内存能得到的最大价值
1 #include <algorithm> 2 #include <cstdio> 3 4 using namespace std; 5 6 const int N(119); 7 const int M(555); 8 int n,m,w[N],v[N],f[N][M]; 9 10 int hed[N],had[N],sumedge; 11 struct Edge 12 { 13 int v,next; 14 Edge(int v=0,int next=0): 15 v(v),next(next){} 16 }edge[M<<1]; 17 void ins(int u,int v,int *head) 18 { 19 edge[++sumedge]=Edge(v,head[u]); 20 head[u]=sumedge; 21 } 22 23 int tim,dfn[N],low[N]; 24 int Stack[N],instack[N],top; 25 int sumcol,col[N],cval[N],cw[N]; 26 void DFS(int now) 27 { 28 dfn[now]=low[now]=++tim; 29 Stack[++top]=now; instack[now]=1; 30 for(int i=hed[now];i;i=edge[i].next) 31 { 32 int v=edge[i].v; 33 if(!dfn[v]) DFS(v),low[now]=min(low[now],low[v]); 34 else if(instack[v]) low[now]=min(low[now],dfn[v]); 35 } 36 if(low[now]==dfn[now]) 37 { 38 col[now]=++sumcol; 39 cw[sumcol]+=w[now]; 40 cval[sumcol]+=v[now]; 41 for(;now!=Stack[top];top--) 42 { 43 col[Stack[top]]=sumcol; 44 cw[sumcol]+=w[Stack[top]]; 45 cval[sumcol]+=v[Stack[top]]; 46 instack[Stack[top]]=0; 47 } 48 instack[now]=0;top--; 49 } 50 } 51 52 int dad[N],root; 53 void Get_tree() 54 { 55 for(int i=1;i<=n;i++) 56 for(int j=hed[i];j;j=edge[j].next) 57 { 58 if(col[i]==col[edge[j].v]) continue; 59 dad[col[edge[j].v]]=col[i]; 60 ins(col[i],col[edge[j].v],had); 61 } 62 } 63 void DP(int x) 64 { 65 for(int i=had[x];i;i=edge[i].next) 66 { 67 DP(edge[i].v); 68 for(int j=m-cw[x];j>=0;j--) 69 for(int k=0;k<=j;k++) 70 f[x][j]=max(f[x][j],f[x][k]+f[edge[i].v][j-k]); 71 } 72 for(int i=m;i>=0;i--) 73 { 74 if(i>=cw[x]) f[x][i]=f[x][i-cw[x]]+cval[x]; 75 else f[x][i]=0; 76 } 77 } 78 79 int main() 80 { 81 // freopen("install.in","r",stdin); 82 // freopen("install.out","w",stdout); 83 scanf("%d%d",&n,&m); 84 for(int i=1;i<=n;i++) scanf("%d",w+i); 85 for(int i=1;i<=n;i++) scanf("%d",v+i); 86 for(int i=1,x;i<=n;i++) 87 { 88 scanf("%d",&x); 89 if(x) ins(x,i,hed); 90 } 91 for(int i=1;i<=n;i++) 92 if(!dfn[i]) DFS(i); 93 Get_tree(); 94 for(int i=1;i<=sumcol;i++) 95 if(!dad[i]) 96 { 97 dad[i]=1; 98 ins(sumcol+1,i,had); 99 } 100 DP(sumcol+1); 101 printf("%d",f[sumcol+1][m]); 102 return 0; 103 }