zoukankan      html  css  js  c++  java
  • bzoj2427: [HAOI2010]软件安装

    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

    HINT

     

    Source

     
    题解:
    先tarjan缩下点,使其变成一棵树,然后我们就可以进行树上背包了
    设f[u][i]表示选到u,用了空间i,得到的最大收益是多少
    O(nm2)的转移显然,但其实可以优化到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
    ",ans);
    79     return 0;
    80 }
  • 相关阅读:
    Java实现 LeetCode 56 合并区间
    JQuery实现对html结点的操作(创建,添加,删除)
    JQuery实现对html结点的操作(创建,添加,删除)
    JQuery实现对html结点的操作(创建,添加,删除)
    Java实现 LeetCode 55 跳跃游戏
    Java实现 LeetCode 55 跳跃游戏
    Java实现 LeetCode 55 跳跃游戏
    Java实现 LeetCode 54 螺旋矩阵
    Java实现 LeetCode 54 螺旋矩阵
    Java实现 LeetCode 54 螺旋矩阵
  • 原文地址:https://www.cnblogs.com/chenyushuo/p/5499649.html
Copyright © 2011-2022 走看看