zoukankan      html  css  js  c++  java
  • [HAOI 2010]软件安装

    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

    题解

    比较裸的树上背包...只不过可能成环比较坑。

    $tarjan$缩点之后再全部连向一个虚点,直接树形$DP$。

     1 //It is made by Awson on 2017.11.5
     2 #include <set>
     3 #include <map>
     4 #include <cmath>
     5 #include <ctime>
     6 #include <stack>
     7 #include <queue>
     8 #include <vector>
     9 #include <string>
    10 #include <cstdio>
    11 #include <cstdlib>
    12 #include <cstring>
    13 #include <iostream>
    14 #include <algorithm>
    15 #define LL long long
    16 #define Min(a, b) ((a) < (b) ? (a) : (b))
    17 #define Max(a, b) ((a) > (b) ? (a) : (b))
    18 #define Abs(x) ((x) < 0 ? (-(x)) : (x))
    19 using namespace std;
    20 const int N = 100;
    21 const int M = 500;
    22 
    23 int n, m;
    24 int W[N+5], V[N+5], w[N+5], v[N+5], d[N+5];
    25 struct tt {
    26     int to, next;
    27 }edge[N+5];
    28 int path[N+5], top;
    29 int dfn[N+5], low[N+5], cnt_time;
    30 stack<int>S;
    31 bool vis[N+5], in[N+5];
    32 int sccno[N+5], sccnum;
    33 int f[N+5][M+5];
    34 
    35 void tarjan(int x) {
    36     dfn[x] = low[x] = ++cnt_time; S.push(x); vis[x] = 1;
    37     for (int i = path[x]; i; i = edge[i].next) {
    38         if (vis[edge[i].to]) low[x] = Min(low[x], dfn[edge[i].to]);
    39         else if (!dfn[edge[i].to]) {
    40             tarjan(edge[i].to); low[x] = Min(low[x], low[edge[i].to]);
    41         }
    42     }
    43     if (dfn[x] == low[x]) {
    44         sccnum++; int u = -1;
    45         do {
    46             u = S.top(); S.pop();
    47             vis[u] = 0, sccno[u] = sccnum;
    48             w[sccnum] += W[u], v[sccnum] += V[u];
    49         }while (u != x);
    50     }
    51 }
    52 void dfs(int u) {
    53     for (int i = path[u]; i; i = edge[i].next) {
    54         dfs(edge[i].to);
    55         for (int j = m; j >= 0; j--)
    56             for (int k = 0; k <= j; k++)
    57                 f[u][j] = Max(f[u][k]+f[edge[i].to][j-k], f[u][j]);
    58     }
    59     for (int i = m; i >= 0; i--) {
    60         if (i-w[u] >= 0) f[u][i] = f[u][i-w[u]]+v[u];
    61         else f[u][i] = 0;
    62     }
    63 }
    64 void add(int u, int v) {
    65     edge[++top].to = v;
    66     edge[top].next = path[u];
    67     path[u] = top;
    68 }
    69 void work() {
    70     scanf("%d%d", &n, &m);
    71     for (int i = 1; i <= n; i++) scanf("%d", &W[i]);
    72     for (int i = 1; i <= n; i++) scanf("%d", &V[i]);
    73     for (int i = 1; i <= n; i++) {
    74         scanf("%d", &d[i]); add(d[i], i);
    75     }
    76     for (int i = 1; i <= n; i++) if (!dfn[i]) tarjan(i); 
    77     memset(path, 0, sizeof(path)); top = 0;
    78     for (int i = 1; i <= n; i++) if (sccno[i] != sccno[d[i]]) add(sccno[d[i]], sccno[i]), in[sccno[i]] = 1;
    79     for (int i = 1; i <= sccnum; i++) if (!in[i]) add(0, i);
    80     dfs(0);
    81     int ans = 0;
    82     for (int i = 0; i <= m; i++) ans = Max(f[0][i], ans);
    83     printf("%d", ans);
    84 }
    85 int main() {
    86     work();
    87     return 0;
    88 }
  • 相关阅读:
    完全背包 基础
    hdoj_2546饭卡(强忍悲痛,好好写题解)
    蓝桥杯--猜字母 学到了!
    Common Subsequence
    Ansible ad-hoc 手册(3)
    ansible playbook 以及变量(2)
    Ansible安装以及常用模块操作(1)
    zabbix3.4自定义触发器(4)
    zabbix3.4自定义监控项(3)
    zabbix3.4监控一台主机(2)
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7787004.html
Copyright © 2011-2022 走看看