bzoj2427[HAOI2010]软件安装

bzoj2427[HAOI2010]软件安装

题意:

有n个软件,每个大小为wi,价值为vi,同时每个软件依赖0个或一个其他软件,要求在大小不超过的m的前提下得到最大价值。n≤100,m≤500。

题解:

缩点然后做“树上背包dp”,具体看代码,注意里面用到了滚动数组。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define inc(i,j,k) for(int i=j;i<=k;i++)
 5 #define dec(i,j,k) for(int i=j;i>=k;i--)
 6 #define maxn 150
 7 using namespace std;
 8 
 9 int bel[maxn],scc,dfn[maxn],low[maxn],tim,st[maxn],top,sv[maxn],sw[maxn],v[maxn],w[maxn]; bool inst[maxn],ok[maxn];
10 struct e1{int f,t,n;}; e1 es1[maxn*5]; int g1[maxn],ess1;
11 void pe1(int f,int t){es1[++ess1]=(e1){f,t,g1[f]}; g1[f]=ess1;}
12 struct e2{int t,n;}; e2 es2[maxn*10]; int g2[maxn],ess2;
13 void pe2(int f,int t){es2[++ess2]=(e2){t,g2[f]}; g2[f]=ess2; ok[t]=1;}
14 void init(){
15     ess1=ess2=0; memset(g1,0,sizeof(g1)); memset(g2,0,sizeof(g2));
16     tim=scc=0; memset(inst,0,sizeof(inst)); memset(dfn,0,sizeof(dfn));
17 }
18 void tarjan(int x){
19     dfn[x]=low[x]=++tim; st[++top]=x; inst[x]=1;
20     for(int i=g1[x];i;i=es1[i].n){
21         if(!dfn[es1[i].t]){
22             tarjan(es1[i].t); low[x]=min(low[x],low[es1[i].t]);
23         }else if(inst[es1[i].t])low[x]=min(low[x],dfn[es1[i].t]);
24     }
25     if(dfn[x]==low[x]){
26         scc++; int y=0; while(x!=y)y=st[top],bel[y]=scc,sv[scc]+=v[y],sw[scc]+=w[y],inst[y]=0,top--;
27     }
28 }
29 void build(){inc(i,1,ess1)if(bel[es1[i].f]!=bel[es1[i].t])pe2(bel[es1[i].f],bel[es1[i].t]);}
30 int f[maxn][maxn*5],n,m;
31 void dfs(int x){
32     for(int i=g2[x];i;i=es2[i].n){
33         dfs(es2[i].t);
34         dec(j,m-sw[x],0)inc(k,0,j)f[x][j]=max(f[x][j],f[x][k]+f[es2[i].t][j-k]);
35     }
36     dec(j,m,0)if(j>=sw[x])f[x][j]=f[x][j-sw[x]]+sv[x];else f[x][j]=0;
37 }
38 inline int read(){
39     char ch=getchar(); int f=1,x=0;
40     while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
41     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
42     return f*x;
43 }
44 int main(){
45     n=read(); m=read(); inc(i,1,n)w[i]=read(); inc(i,1,n)v[i]=read(); init();
46     inc(i,1,n){int a=read(); if(a)pe1(a,i);} inc(i,1,n)if(!dfn[i])tarjan(i); build();
47     inc(i,1,scc)if(!ok[i])pe2(scc+1,i); dfs(scc+1); printf("%d",f[scc+1][m]); return 0;
48 }

 

20160614

posted @ 2016-08-17 14:20  YuanZiming  阅读(169)  评论(0编辑  收藏  举报