bzoj2427: [HAOI2010]軟件安裝

Description

如今咱們的手頭有N個軟件,對於一個軟件i,它要佔用Wi的磁盤空間,它的價值爲Vi。咱們但願從中選擇一些軟件安裝到一臺磁盤容量爲M計算機上,使得這些軟件的價值儘量大(即Vi的和最大)。

可是如今有個問題:軟件之間存在依賴關係,即軟件i只有在安裝了軟件j(包括軟件j的直接或間接依賴)的狀況下才能正確工做(軟件i依賴軟件j)。幸運的是,一個軟件最多依賴另一個軟件。若是一個軟件不能正常工做,那麼它可以發揮的做用爲0。

咱們如今知道了軟件之間的依賴關係:軟件i依賴軟件Di。如今請你設計出一種方案,安裝價值儘可能大的軟件。一個軟件只能被安裝一次,若是一個軟件沒有依賴則Di=0,這時只要這個軟件安裝了,它就能正常工做。

php

 

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 )

ios

 

Output

一個整數,表明最大價值。git

 

Sample Input

3 10
5 5 6
2 3 4
0 1 1

Sample Output

5

HINT

 

Source

Day2優化

 
題解:
先tarjan縮下點,使其變成一棵樹,而後咱們就能夠進行樹上揹包了
設f[u][i]表示選到u,用了空間i,獲得的最大收益是多少
O(nm 2)的轉移顯然,但其實能夠優化到O(nm)
設u的一個兒子是v,則咱們能夠把f[u]做爲初始狀態直接付給f[v],而後就能夠減小一個m的轉移複雜度
注意把f[u]做爲初始狀態直接付給f[v]時,f[v]的第二維有下限(就是v及其全部祖先所佔的空間和)
code:
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 char ch;
 8 bool ok;
 9 void read(int &x){
10     ok=0;
11     for (ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
12     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
13     if (ok) x=-x;
14 }
15 const int maxn=105;
16 const int maxm=505;
17 const int inf=1010580541;
18 int n,m,a[maxn],b[maxn],x,ans;
19 int f[maxn][maxm],g[maxm];
20 int idx,dfn[maxn],low[maxn],stack[maxn],top,cnt,bel[maxn],siz[maxn],val[maxn],deg[maxn];
21 bool in[maxn],bo[maxn];
22 struct Graph{
23     int tot,now[maxn],son[maxn],pre[maxn];
24     void put(int a,int b){pre[++tot]=now[a],now[a]=tot,son[tot]=b;}
25     void dfs(int u){
26         dfn[u]=low[u]=++idx,stack[++top]=u,in[u]=1;
27         for (int p=now[u],v=son[p];p;p=pre[p],v=son[p])
28             if (!dfn[v]) dfs(v),low[u]=min(low[u],low[v]);
29             else if (in[v]) low[u]=min(low[u],dfn[v]);
30         if (dfn[u]==low[u]){
31             int v; ++cnt;
32             do{v=stack[top--],bel[v]=cnt,siz[cnt]+=a[v],val[cnt]+=b[v],in[v]=0;}while (u!=v);
33         }
34     }
35     /*void dp(int u){
36         bo[u]=1;
37         memset(f[u],195,sizeof(f[u]));
38         f[u][siz[u]]=val[u];
39         for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]) if (!bo[v]){
40             dp(v);
41             memcpy(g,f[u],sizeof(g));
42             for (int i=0;i<=m;i++) for (int j=m;j>=i;j--) g[j]=max(g[j],f[v][i]+f[u][j-i]);
43             memcpy(f[u],g,sizeof(g));
44         }
45         f[u][0]=max(f[u][0],0);
46     }*/
47     /*void dp(int u,int m){
48         //cout<<u<<' '<<m<<endl;
49         bo[u]=1;
50         for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]) if (!bo[v]){
51             for (int i=0;i<=m;i++) f[v][i]=f[u][i];
52             dp(v,m-siz[v]);
53             for (int i=siz[v];i<=m;i++) f[u][i]=max(f[u][i],f[v][i-siz[v]]+val[v]);
54         }
55     }*/
56     void dp(int u,int low){
57         bo[u]=1;
58         for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]) if (!bo[v]){
59             for (int i=low;i<=m-siz[v];i++) f[v][i+siz[v]]=f[u][i]+val[v];
60             dp(v,low+siz[v]);
61             for (int i=low+siz[v];i<=m;i++) f[u][i]=max(f[u][i],f[v][i]);
62         }
63     }
64 }G1,G2;
65 int main(){
66     read(n),read(m);
67     for (int i=1;i<=n;i++) read(a[i]);
68     for (int i=1;i<=n;i++) read(b[i]);
69     for (int i=1;i<=n;i++) read(x),G1.put(x,i);
70     for (int i=0;i<=n;i++) if (!dfn[i]) G1.dfs(i);
71     for (int u=0;u<=n;u++) for (int p=G1.now[u],v=G1.son[p];p;p=G1.pre[p],v=G1.son[p])
72         if (bel[u]!=bel[v]) G2.put(bel[u],bel[v]),deg[bel[v]]++;
73     for (int u=1;u<=n;u++) if (!deg[bel[u]]) G2.put(bel[0],bel[u]);
74     //G2.dp(bel[0]);
75     //G2.dp(bel[0],m);
76     G2.dp(bel[0],0);
77     for (int i=0;i<=m;i++) ans=max(ans,f[bel[0]][i]);
78     printf("%d\n",ans);
79     return 0;
80 }
相關文章
相關標籤/搜索