现在我们的手头有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 #include<cstring>
2 #include<cmath>
3 #include<iostream>
4 #include<algorithm>
5 #include<cstdio>
6
7 #define N 107
8 #define M 507
9 using namespace std;
10 inline int read()
11 {
12 int x=0,f=1;char ch=getchar();
13 while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();}
14 while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-‘0‘;ch=getchar();}
15 return x*f;
16 }
17
18 int n,m,cnt,scc,ind,top;
19 int v[N],w[N];
20 int sv[N],sw[N];
21 int dfn[N],low[N],belong[N];
22 int q[N],f[N][M],in[M];
23 struct edge{
24 int to,next;
25 }e[M],ed[M];int last[N],last2[N];
26 bool inq[N];
27
28 void insert(int u,int v){e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;}
29 void insert2(int u,int v)
30 {
31 in[v]=1;
32 ed[++cnt].to=v;ed[cnt].next=last2[u];last2[u]=cnt;
33 }
34 void tarjan(int x)
35 {
36 int now=0;
37 low[x]=dfn[x]=++ind;
38 q[++top]=x;inq[x]=1;
39 for(int i=last[x];i;i=e[i].next)
40 if(!dfn[e[i].to])
41 {
42 tarjan(e[i].to);
43 low[x]=min(low[x],low[e[i].to]);
44 }
45 else if(inq[e[i].to])
46 low[x]=min(low[x],dfn[e[i].to]);
47 if(low[x]==dfn[x])
48 {
49 scc++;
50 while(now!=x)
51 {
52 now=q[top--];inq[now]=0;
53 belong[now]=scc;
54 sv[scc]+=v[now];
55 sw[scc]+=w[now];
56 }
57 }
58 }
59 void rebuild()
60 {
61 cnt=0;
62 for(int x=1;x<=n;x++)
63 for(int i=last[x];i;i=e[i].next)
64 if(belong[e[i].to]!=belong[x])
65 insert2(belong[x],belong[e[i].to]);
66 }
67 void dp(int x)
68 {
69 for(int i=last2[x];i;i=ed[i].next)
70 {
71 dp(ed[i].to);
72 for(int j=m-sw[x];j>=0;j--)
73 {
74 for(int k=0;k<=j;k++)
75 f[x][j]=max(f[x][j],f[x][k]+f[ed[i].to][j-k]);
76 }
77 }
78 for(int j=m;j>=0;j--)
79 {
80 if(j>=sw[x])f[x][j]=f[x][j-sw[x]]+sv[x];
81 else f[x][j]=0;
82 }
83 }
84 int main()
85 {
86 n=read();m=read();
87 for(int i=1;i<=n;i++) w[i]=read();
88 for(int i=1;i<=n;i++) v[i]=read();
89 for(int i=1;i<=n;i++)
90 {
91 int x=read();
92 if(x)insert(x,i);
93 }
94 for(int i=1;i<=n;i++)
95 if(!dfn[i])tarjan(i);
96 rebuild();
97 for(int i=1;i<=scc;i++)
98 if(!in[i])
99 insert2(scc+1,i);
100 dp(scc+1);
101 printf("%d\n",f[scc+1][m]);
102 }