• P2515 [HAOI2010]软件安装


    P2515 [HAOI2010]软件安装

    题目描述

    现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi。我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大)。

    但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j)。幸运的是,一个软件最多依赖另外一个软件。如果一个软件不能正常工作,那么它能够发挥的作用为0。

    我们现在知道了软件之间的依赖关系:软件i依赖软件Di。现在请你设计出一种方案,安装价值尽量大的软件。一个软件只能被安装一次,如果一个软件没有依赖则Di=0,这时只要这个软件安装了,它就能正常工作。

    输入输出格式

    输入格式:

    第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 )

    输出格式:

    一个整数,代表最大价值

    输入输出样例

    输入样例#1: 复制
    3 10
    5 5 6
    2 3 4
    0 1 1
    输出样例#1: 复制
    5

    分析

    tarjan缩点+树形背包(好难调试啊啊)

    code

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<cstdlib>
     6 #include<vector>
     7 #include<iostream>
     8 
     9 using namespace std;
    10 
    11 const int N = 210;
    12 const int M = 510;
    13 struct Edge{
    14     int to,nxt;
    15 }e[M];
    16 int head[N],dfn[N],low[N],st[N],bel[N];
    17 int w[N],W[N],v[N],V[N],dp[N][M],ru[N];
    18 bool vis[N];
    19 int cnt,tn,tot,top,n,m;
    20 vector<int>s[N];
    21 
    22 inline char nc() {
    23     static char buf[100000],*p1 = buf,*p2 = buf;
    24     return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2) ? EOF : *p1++;
    25 }
    26 inline int read() {
    27     int x = 0,f = 1;char ch = nc();
    28     for (; ch<'0'||ch>'9'; ch = nc()) 
    29         if (ch=='-') f = -1;
    30     for (; ch>='0'&&ch<='9'; ch = nc()) 
    31         x = x*10+ch-'0';
    32     return x * f;
    33 }
    34 
    35 inline void add_edge(int u,int v) {
    36     e[++tot].to = v,e[tot].nxt = head[u],head[u] = tot;
    37 }
    38 
    39 void tarjan(int u) {
    40     dfn[u] = low[u] = ++tn;
    41     st[++top] = u;
    42     vis[u] = true;
    43     for (int i=head[u]; i; i=e[i].nxt) {
    44         int v = e[i].to;
    45         if (!dfn[v]) {
    46             tarjan(v);
    47             low[u] = min(low[u],low[v]);
    48         }
    49         else if (vis[v]) 
    50             low[u] = min(low[u],dfn[v]);
    51     }
    52     if (low[u]==dfn[u]) {
    53         ++cnt;
    54         do { 
    55             vis[st[top]] = false;
    56             bel[st[top]] = cnt;
    57             W[cnt] += w[st[top]];
    58             V[cnt] += v[st[top]];
    59             top--;
    60         } while (st[top+1] != u);
    61     }
    62 }
    63 void dfs(int u) {
    64    for (int i=V[u]; i<=m; ++i) dp[u][i] = W[u]; 
    65     int tmp = s[u].size();
    66     for (int i=0; i<tmp; ++i) {
    67         int v = s[u][i];
    68         dfs(v);
    69         for (int j=m; j>=V[u]; --j) 
    70             for (int k=0; k<=j-V[u]; ++k)
    71                 dp[u][j] = max(dp[u][j],dp[v][k]+dp[u][j-k]);
    72     }
    73 }
    74 
    75 int main() {
    76 
    77     n = read(),m = read();
    78     for (int i=1; i<=n; ++i) v[i] = read();
    79     for (int i=1; i<=n; ++i) w[i] = read();
    80     for (int x,i=1; i<=n; ++i) {
    81         x = read();if (x) add_edge(x,i);
    82     }
    83     for (int i=1; i<=n; ++i) 
    84         if (!dfn[i]) tarjan(i);
    85 
    86     for (int i=1; i<=n; ++i) 
    87         for (int j=head[i]; j; j=e[j].nxt) {
    88             if (bel[i] != bel[e[j].to]) {
    89                 s[bel[i]].push_back(bel[e[j].to]);
    90                 ru[bel[e[j].to]]++;
    91             }
    92         }
    93     for (int i=1; i<=cnt; ++i) 
    94         if (!ru[i]) s[0].push_back(i);
    95     dfs(0);
    96     printf("%d",dp[0][m]);
    97     return 0;
    98 }
  • 相关阅读:
    API
    API
    for in
    event flow
    object
    Report of program history
    正则表达式
    伪类与伪元素
    Position
    js学习之原型(补充)
  • 原文地址:https://www.cnblogs.com/mjtcn/p/7898931.html
Copyright © 2020-2023  润新知