洛谷——P2515 [HAOI2010]软件安装

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 }

 

posted @ 2017-07-17 14:57  Aptal丶  阅读(256)  评论(0编辑  收藏  举报