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

    2427: [HAOI2010]软件安装

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 1512  Solved: 584
    [Submit][Status][Discuss]

    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

     
    【题解】
    先缩点。
    两种解法。
     
    ‘’1、若把当前图中的每个结点成1个物品,磁盘空间当成背包,则类似有依赖关系的背包问题,可以用动态规划解决。
    将所有的树重新编号,设共有x棵树,每棵树的根结点的编号r[1],r[2],…,r[x];
    设f(r[i],j)表示第i棵树前拥有j的资源,则

    tree(r[i],k)表示第i棵树拥有k资源的最大代价,这个值可以用上述公式处理即,去掉根后转化森林,用背包问题解决。
    1<=i<=N, 0<=k<=j<=M
    时间复杂度O(NM2)

    2、将森林转化为二叉树后,采用树型动态规划一次求出。


    设f(i,j)表示以i为根结点的二叉树分配j资源的最大价值
    ‘’
    ——by 朱全民
    这里采用第二种
    做得时候注意,森林->二叉树要虚一个空节点作为根,不能任选一棵树的根作根(被卡了四个点)
     
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstdlib>
      4 #include <cstring>
      5 #include <cmath> 
      6 #include <algorithm>
      7 #define min(a, b) ((a) < (b) ? (a) : (b))
      8 #define max(a, b) ((a) > (b) ? (a) : (b))
      9 
     10 inline void read(int &x)
     11 {
     12     x = 0;char ch = getchar(), c = ch;
     13     while(ch < '0' || ch > '9')c = ch, ch = getchar();
     14     while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
     15     if(c == '-')x = -x;
     16 }
     17 
     18 const int INF = 0x3f3f3f3f; 
     19 const int MAXN = 100 + 10;
     20 const int MAXM = 500 + 10;
     21 
     22 int n,m,cost[MAXN],value[MAXN];
     23 
     24 struct Edge
     25 {
     26     int u,v,next;
     27     Edge(int _u, int _v, int _next){u = _u;v = _v;next = _next;}
     28     Edge(){}
     29 }edge[MAXN << 1];
     30 int head[MAXN], cnt;
     31 
     32 inline void insert(int a, int b)
     33 {
     34     edge[++cnt] = Edge(a, b, head[a]);
     35     head[a] = cnt;
     36 }
     37 
     38 int b[MAXN],bb[MAXN],low[MAXN],dfn[MAXN],belong[MAXN],group,tot,stack[MAXN],top;
     39 
     40 void tarjan_dfs(int u)
     41 {
     42     dfn[u] = low[u] = ++tot;    
     43     b[u] = bb[u] = 1;
     44     stack[++top] = u;
     45     for(register int pos = head[u];pos;pos = edge[pos].next)
     46     {
     47         int v = edge[pos].v;
     48         if(!b[v])
     49         {
     50             tarjan_dfs(v);
     51             low[u] = min(low[u], low[v]);
     52         }
     53         else if(bb[v] && low[u] > dfn[v])
     54             low[u] = dfn[v];
     55     }
     56     if(low[u] == dfn[u])
     57     {
     58         ++ group;
     59         int now = 0;
     60         while(now != u)
     61         {
     62             now = stack[top --];
     63             belong[now] = group;
     64             bb[now] = false;
     65         }
     66     }
     67 }
     68 
     69 int cost2[MAXN],value2[MAXN],l[MAXN],r[MAXN],fa2[MAXN];
     70 
     71 void tarjan()
     72 {
     73     for(register int i = 1;i <= n;++ i) if(!b[i]) tarjan_dfs(i);
     74     for(register int u = 1;u <= n;++ u)
     75     {
     76         for(register int pos = head[u];pos;pos = edge[pos].next)
     77         {
     78             int v = edge[pos].v;
     79             if(belong[v] != belong[u])
     80                 fa2[belong[v]] = belong[u];
     81         }
     82         cost2[belong[u]] += cost[u];
     83         value2[belong[u]] += value[u]; 
     84     }
     85     for(register int i = 1;i <= group;++ i)
     86         if(fa2[i])r[i] = l[fa2[i]], l[fa2[i]] = i;
     87 }
     88 
     89 int dp[MAXN][MAXM],dpb[MAXN];
     90 
     91 void DP(int u)
     92 {
     93     if(!u || dpb[u])return; 
     94     dpb[u] = 1;
     95 /*
     96 dp[i][j]表示i和i右边的兄弟消耗磁盘空间j的最大价值
     97 dp[i][j] = max{
     98 选    f[l[i]][a] + f[r[i]][j - a  - cost[i]] + value[i] 
     99 
    100 不选  f[r[i]][j]
    101 }
    102 */
    103     DP(l[u]), DP(r[u]);
    104     for(register int j = 0;j <= m;++ j)
    105     {
    106         for(register int a = 0;a <= m;++ a)
    107         {
    108             //dp[u][j] = max(dp[u][j], dp[u][j - 1]);
    109             if(j - a - cost2[u] >= 0)    dp[u][j] = max(dp[u][j], dp[l[u]][a] + dp[r[u]][j - a - cost2[u]] + value2[u]);
    110             dp[u][j] = max(dp[u][j], dp[r[u]][j]);
    111         }
    112     } 
    113 }
    114 
    115 int main()
    116 {
    117     read(n), read(m);
    118     register int tmp;
    119     for(register int i = 1;i <= n;++ i) read(cost[i]);
    120     for(register int i = 1;i <= n;++ i) read(value[i]);
    121     for(register int i = 1;i <= n;++ i) 
    122     {
    123         read(tmp);
    124         if(tmp)insert(tmp, i);
    125     }
    126     tarjan();
    127     int root = 1;
    128     while(!l[root] && root <= group)++ root;
    129     if(root <= group)
    130     {
    131         while(fa2[root])root = fa2[root];
    132         l[group + 1] = root;
    133         fa2[root] = group + 1,
    134         root = group + 1;
    135         ++ group;
    136     }
    137     else
    138         root = group + 1;
    139     for(register int i = 1;i <= group;++ i) 
    140         if(!fa2[i] && i != root) r[i] = l[root], l[root] = i, fa2[i] = root;
    141     cost2[root] = value2[root] = 0;
    142     DP(root);
    143     printf("%d", dp[root][m]);
    144     return 0;
    145 }
    BZOJ2427
  • 相关阅读:
    那些离不开的 Chrome 扩展插件
    Spring Boot 实战 —— 入门
    Maven 学习笔记
    Linux lvm 分区知识笔记
    Linux 双向 SSH 免密登录
    CentOS Yum 源搭建
    Ubuntu 系统学习
    iOS 测试三方 KIF 的那些事
    Swift 网络请求数据与解析
    iOS Plist 文件的 增 删 改
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/7502970.html
Copyright © 2011-2022 走看看