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 }
  • 相关阅读:
    几种常见的Map的区别
    BlockingQueue详解
    Android开发过程中内存泄露检测
    Android studio 技巧设置(持续更新中)
    Android Support兼容包详解
    单例模式的饿汉式为什么需要双重锁定
    View分析
    Activity的启动流程分析
    LeetCode第十四题-字符串数组中最长的共同前缀
    LeetCode第十三题-将罗马数字转化为数字
  • 原文地址:https://www.cnblogs.com/chenyushuo/p/5499649.html
Copyright © 2011-2022 走看看