洛谷 P2515 [HAOI2010]软件安装

来源:互联网 发布:塔吉特百货大数据 编辑:程序博客网 时间:2024/06/06 19:03

题目描述

现在我们的手头有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 105 5 62 3 40 1 1

输出样例#1:

5


哈哈,又是一道好题!
思路还是比较好想的,先tarjan缩点,重新建图,原图从基环树变成树,做树形dp,然而本人比较弱,树形dp没有一次写对。

#include<iostream>#include<cstring>#include<cstdio>#include<stack>using namespace std;const int N=105;int n,m,cnt,dcnt,tim,d[N],c[N],w[N],hd[N],dfn[N],low[N],cc[N],ww[N],f[N][505],belong[N],du[N];bool ins[N];stack<int>stk;struct edge{int to,nxt;}v[N];void addedge(int x,int y){v[++cnt].to=y;v[cnt].nxt=hd[x];hd[x]=cnt;}void tarjan(int u){dfn[u]=low[u]=++tim;ins[u]=1;stk.push(u);for(int i=hd[u];i;i=v[i].nxt){if(!dfn[v[i].to]){tarjan(v[i].to);low[u]=min(low[u],low[v[i].to]);}else if(ins[v[i].to])low[u]=min(low[u],dfn[v[i].to]);}if(dfn[u]==low[u]){++dcnt;while(1){int t=stk.top();stk.pop();ins[t]=0;belong[t]=dcnt;if(u==t)break;}}}void dp(int u,int fa){for(int i=hd[u];i;i=v[i].nxt)if(v[i].to!=fa){dp(v[i].to,u);for(int j=m-cc[u];j>=1;j--)for(int k=1;k<=j;k++)f[u][j]=max(f[u][j],f[u][j-k]+f[v[i].to][k]);}for(int i=m;i>=0;i--)if(i>=cc[u])f[u][i]=f[u][i-cc[u]]+ww[u];elsef[u][i]=0;}int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",&c[i]);for(int i=1;i<=n;i++)scanf("%d",&w[i]);for(int i=1;i<=n;i++){scanf("%d",&d[i]);if(d[i])addedge(d[i],i);}//缩点 for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);//重新建图 for(int i=1;i<=n;i++)cc[belong[i]]+=c[i],ww[belong[i]]+=w[i];memset(hd,0,sizeof(hd));cnt=0;for(int i=1;i<=n;i++)if(d[i]&&belong[d[i]]!=belong[i]){addedge(belong[d[i]],belong[i]);du[belong[i]]++;}for(int i=1;i<=dcnt;i++)if(!du[i])addedge(0,i);//树形dp dp(0,-1);printf("%d\n",f[0][m]);return 0;}

0 0
原创粉丝点击