1. 程式人生 > >洛谷 P2515 [HAOI2010]軟件安裝

洛谷 P2515 [HAOI2010]軟件安裝

blank tar digi span cst https 格式 getchar add

題目描述

現在我們的手頭有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

Tarjan縮點+樹形dp

屠龍寶刀點擊就送

#include <ctype.h>
#include <cstdio>
#define N 605

void read(int &x)
{
    x=0;bool f=0;
    char ch=getchar();
    while(!isdigit(ch)) {if(ch==-) f=1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-0;ch=getchar();}
    x=f?(~x)+1:x;
}
struct
node { int next,to; }edge[N<<1]; struct node2 { int next,to; }edge2[N<<1]; struct thing { int v,w; }th[N]; bool in[N],instack[N]; int head2[N],cnt2,f[N][N],w[N],v[N],stack[N],top,n,m,head[N],cnt,sumcol,col[N],dfn[N],low[N],tim; void add(int u,int v) { edge[++cnt].next=head[u]; edge[cnt].to=v; head[u]=cnt; } int min(int a,int b){return a>b?b:a;} int max(int a,int b){return a>b?a:b;} void tarjan(int x) { dfn[x]=low[x]=++tim; instack[x]=1; stack[++top]=x; for(int i=head[x];i;i=edge[i].next) { int v=edge[i].to; if(instack[v]) low[x]=min(low[x],dfn[v]); if(!dfn[v]) tarjan(v),low[x]=min(low[x],low[v]); } if(low[x]==dfn[x]) { int t; sumcol++; do { t=stack[top--]; instack[t]=false; col[t]=sumcol; th[sumcol].v+=v[t]; th[sumcol].w+=w[t]; }while(t!=x); } } void dp(int x)//此處DP為樹上01背包 { for(int i=head2[x];i;i=edge2[i].next) { dp(edge2[i].to);//延伸的點繼續dp for(int j=m-th[x].w;j>=0;j--) { for(int k=0;k<=j;k++) f[x][j]=max(f[x][j],f[x][k]+f[edge2[i].to][j-k]); } } for(int j=m;j>=0;j--) { if(j>=th[x].w) f[x][j]=f[x][j-th[x].w]+th[x].v; else f[x][j]=0; } } void add2(int u,int v) { edge2[++cnt2].next=head2[u]; edge2[cnt2].to=v; head2[u]=cnt2; } void rebuild() { for(int i=1;i<=n;i++) { for(int j=head[i];j;j=edge[j].next) { int v=edge[j].to; if(col[v]!=col[i]) { in[col[v]]=1; add2(col[i],col[v]); } } } } int main() { read(n);read(m); for(int i=1;i<=n;i++) read(w[i]); for(int i=1;i<=n;i++) read(v[i]); for(int x,i=1;i<=n;i++) { read(x); if(x) add(x,i); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); rebuild(); for(int i=1;i<=sumcol;i++) { if(!in[i]) { in[i]=1; add2(sumcol+1,i); } } dp(sumcol+1); printf("%d",f[sumcol+1][m]); return 0; }

洛谷 P2515 [HAOI2010]軟件安裝