1. 程式人生 > >BZOJ2427: [HAOI2010]軟件安裝

BZOJ2427: [HAOI2010]軟件安裝

ref 安裝 get cost 代碼 容量 else www ring

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

Sample Output

5 題目傳送門 這個要縮點應該比較好想吧。。。有點像植物大戰僵屍 然後就可以進行樹形dp了 代碼如下:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
struct node{
    int x,y,next;
}a[21000];int len,last[21000];
void ins(int x,int y)
{
    len
++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } int n,m; int tot[510],dfn[510],low[510]; int belong[510],sta[510]; bool v[510]; int cost[510]; int id,cnt,top; int w[510],c[510]; void dfs(int x) { dfn[x]=low[x]=++id; v[x]=true;sta[++top]=x; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(dfn[y]==-1) { dfs(y); low[x]=min(low[x],low[y]); } else if(v[y]==true) low[x]=min(low[x],dfn[y]); } if(dfn[x]==low[x]) { cnt++;int i; do{ i=sta[top--]; belong[i]=cnt; v[i]=false; cost[cnt]+=w[i]; tot[cnt]+=c[i]; }while(i!=x); } } int d[510]; int ru[510]; int total[510]; int f[510][510]; void treedp(int x) { f[x][cost[x]]=tot[x];total[x]=cost[x]; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; treedp(y); for(int i=m;i>cost[x];i--) for(int j=0;j<=total[y];j++) if(i-j>=0&&i-j>=cost[x])f[x][i]=max(f[x][i],f[y][j]+f[x][i-j]); total[x]+=total[y]; } } int main() { scanf("%d%d",&n,&m); len=0;memset(last,0,sizeof(last)); for(int i=1;i<=n;i++)scanf("%d",&w[i]); for(int i=1;i<=n;i++)scanf("%d",&c[i]); for(int i=1;i<=n;i++) { scanf("%d",&d[i]); if(d[i]!=0)ins(d[i],i); } id=cnt=top=0; memset(dfn,-1,sizeof(dfn)); memset(v,false,sizeof(v)); for(int i=1;i<=n;i++) if(dfn[i]==-1) dfs(i); len=0;memset(last,0,sizeof(last)); for(int i=1;i<=n;i++) if(belong[i]!=belong[d[i]]) ins(belong[d[i]],belong[i]),ru[belong[i]]++; for(int i=1;i<=n;i++) if(ru[i]==0) ins(0,i); treedp(0); printf("%d\n",f[0][m]); return 0; }

by_lmy

BZOJ2427: [HAOI2010]軟件安裝