码迷,mamicode.com
首页 > 其他好文 > 详细

【HAOI2010】软件安装

时间:2020-07-16 21:16:41      阅读:45      评论:0      收藏:0      [点我收藏+]

标签:--   计算机   i++   描述   for   磁盘容量   bsp   title   names   

题目描述 

现在我们的手头有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 )

输出描述:

一个整数,代表最大价值。

输入

3 10
5 5 6
2 3 4
0 1 1

输出

5
//缩点是为了处理图中的环,缩点之后就是一个简单的树型背包dp了
#include<bits/stdc++.h>
using namespace std;
const int N = 1e3 + 7;
int dp[N][N], W[N], V[N], w[N], v[N];
int head[N], ver[N], nex[N], tot, n, m;
int in[N], dfn[N], low[N], st[N], vis[N], c[N], cnt, top, num;
vector<int> scc[N];
void add(int x, int y) {
    ver[++tot] = y; nex[tot] = head[x]; head[x] = tot;
}
void tarjan(int x) {
    low[x] = dfn[x] = ++num;
    st[top++] = x;
    vis[x] = 1;
    for (int i = head[x]; i; i = nex[i]) {
        int y = ver[i];
        if (!dfn[y]) {
            tarjan(y);
            low[x] = min(low[x], low[y]);
        } else if (vis[y])
            low[x] = min(low[x], dfn[y]);
    }
    if (low[x] == dfn[x]) {
        int y;
        ++cnt;
        do {
            y = st[--top];
            vis[y] = 0;
            c[y] = cnt;
            v[cnt] += V[y];
            w[cnt] += W[y];
        } while (x != y);
    }
}
void Dp(int x) {
    for (int i = w[x]; i <= m; i++) dp[x][i] = v[x];
    for (int y: scc[x]) {
        Dp(y);
        for (int i = m - w[x]; i >= 0; i--) {
            for (int j = 0; j <= i; j++) {
                dp[x][i + w[x]] = max(dp[x][i + w[x]], dp[x][i + w[x] - j] + dp[y][j]);
            }
        }
    }
}
int main() {
    int x;
    cin >> n >> m;
    for (int i = 1; i <= n; i++) cin >> W[i];
    for (int i = 1; i <= n; i++) cin >> V[i];
    for (int i = 1; i <= n; i++) {
        cin >> x;
        if (x) add(x, i);
    }
    for (int i = 1; i <= n; i++) if (!dfn[i]) tarjan(i);
    for (x = 1; x <= n; x++) {
        for (int j = head[x]; j; j = nex[j]) {
            int y = ver[j];
            if (c[x] != c[y]) scc[c[x]].push_back(c[y]), in[c[y]]++;
        }
    }
    for (int i = 1; i <= cnt; i++) {
        if (!in[i]) scc[0].push_back(i);
    }
    Dp(0);
    cout << dp[0][m] << endl;
    return 0;
}

 

【HAOI2010】软件安装

标签:--   计算机   i++   描述   for   磁盘容量   bsp   title   names   

原文地址:https://www.cnblogs.com/HighLights/p/13323920.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!