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$。

 //It is made by Awson on 2017.11.5
#include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Abs(x) ((x) < 0 ? (-(x)) : (x))
using namespace std;
const int N = ;
const int M = ; int n, m;
int W[N+], V[N+], w[N+], v[N+], d[N+];
struct tt {
int to, next;
}edge[N+];
int path[N+], top;
int dfn[N+], low[N+], cnt_time;
stack<int>S;
bool vis[N+], in[N+];
int sccno[N+], sccnum;
int f[N+][M+]; void tarjan(int x) {
dfn[x] = low[x] = ++cnt_time; S.push(x); vis[x] = ;
for (int i = path[x]; i; i = edge[i].next) {
if (vis[edge[i].to]) low[x] = Min(low[x], dfn[edge[i].to]);
else if (!dfn[edge[i].to]) {
tarjan(edge[i].to); low[x] = Min(low[x], low[edge[i].to]);
}
}
if (dfn[x] == low[x]) {
sccnum++; int u = -;
do {
u = S.top(); S.pop();
vis[u] = , sccno[u] = sccnum;
w[sccnum] += W[u], v[sccnum] += V[u];
}while (u != x);
}
}
void dfs(int u) {
for (int i = path[u]; i; i = edge[i].next) {
dfs(edge[i].to);
for (int j = m; j >= ; j--)
for (int k = ; k <= j; k++)
f[u][j] = Max(f[u][k]+f[edge[i].to][j-k], f[u][j]);
}
for (int i = m; i >= ; i--) {
if (i-w[u] >= ) f[u][i] = f[u][i-w[u]]+v[u];
else f[u][i] = ;
}
}
void add(int u, int v) {
edge[++top].to = v;
edge[top].next = path[u];
path[u] = top;
}
void work() {
scanf("%d%d", &n, &m);
for (int i = ; i <= n; i++) scanf("%d", &W[i]);
for (int i = ; i <= n; i++) scanf("%d", &V[i]);
for (int i = ; i <= n; i++) {
scanf("%d", &d[i]); add(d[i], i);
}
for (int i = ; i <= n; i++) if (!dfn[i]) tarjan(i);
memset(path, , sizeof(path)); top = ;
for (int i = ; i <= n; i++) if (sccno[i] != sccno[d[i]]) add(sccno[d[i]], sccno[i]), in[sccno[i]] = ;
for (int i = ; i <= sccnum; i++) if (!in[i]) add(, i);
dfs();
int ans = ;
for (int i = ; i <= m; i++) ans = Max(f[][i], ans);
printf("%d", ans);
}
int main() {
work();
return ;
}

[HAOI 2010]软件安装的更多相关文章

  1. BZOJ 2427 /HAOI 2010 软件安装 tarjan缩点+树形DP

    终于是道中文题了.... 当时考试的时候就考的这道题.... 果断GG. 思路: 因为有可能存在依赖环,所以呢 先要tarjan一遍 来缩点. 随后就进行一遍树形DP就好了.. x表示当前的节点.j表 ...

  2. Visual Studio 2010软件安装教程

    链接:https://pan.baidu.com/s/10FeLlKpzFcb9yUjm3ZECsg 提取码:pup1 复制这段内容后打开百度网盘手机App,操作更方便哦 1.右击软件压缩包,选择解压 ...

  3. Linux下软件安装方法即路径设置

    Linux下软件安装方法即路径设置 http://www.cnblogs.com/edward259/archive/2010/07/02/1770066.html

  4. CentOS 7下的软件安装方法及策略

    一些废话 2010年开始正式接触Linux,入门发行版是Ubuntu 10.10,后来过渡到Ubunu 11.04,这其中也尝试了很多其他主流的发行版.进入实验室之后,开始用CentOS 5,然后是C ...

  5. VC++2010组件安装失败解决办法

    安装SQLSERVER时,安装不上,总是报错说 VC++2010组件安装错误. 单独安装时,也会报出严重错误无法安装.就是下面这两个 最后到网上找到一个办法解决了:如下: 下载这个软件 Microso ...

  6. Visual Studio 2010详细安装过程

    Visual Studio 2010在目前看来,应该是使用得比较多的一款微软的软件开发工具集合了,因为它具有以下优点:(1)启动速度快:在相同环境下,相比于Visual Studio 2015来说,2 ...

  7. Exchange 2010 详细安装步骤

    工具/原料   系统要求:windows 2008 R2 标准版或者企业版 Exchange Server 2010 SP3:https://www.microsoft.com/en-us/downl ...

  8. 源码包---linux软件安装与管理

    源代码推荐保存位置: /usr/local/src 软件安装位置: /usr/local 如何确定安装过程报错: 安装过程停止 并出现error / warning / no 的提示 ./config ...

  9. yum---Linux软件安装与管理

    查询: yum list #查询所有可用的软件包列表 yum search keywords #搜索服务器上所有和关键字相关的软件包 安装: yum -y install 包名 options: in ...

随机推荐

  1. 使用jmeter+ant进行接口自动化测试(数据驱动)之一:设计jmeter脚本

    最近在做接口测试,因为公司有使用jmeter做接口测试的相关培训资料,所以还是先选择使用jmeter来批量管理接口,进行自动化测试.话不多说,进入正题: 1.使用csv文件保存接口测试用例,方便后期对 ...

  2. 2017-2018-1 20155215 第九周 加分项 PWD命令的实现

    1 学习pwd命令 Linux中用 pwd 命令来查看"当前工作目录"的完整路径. 简单得说,每当你在终端进行操作时,你都会有一个当前工作目录. 在不太确定当前位置时,就会使用pw ...

  3. Java 密码学算法

    Java 密码学算法 候捷老师在< 深入浅出MFC 2e(电子版)>中引用林语堂先生的一句话: 只用一样东西,不明白它的道理,实在不高明 只知道How,不知道Why,出了一点小问题时就无能 ...

  4. 需求分析&原型改进

    需求&原型改进 一.给目标用户展现原型,与目标用户进一步沟通理解需求. 1.用户痛点:需要随时随地练习四则运算,并能看到用户的统计数据. 2.用户反馈:较好地解决练习需求,若能加入班级概念则更 ...

  5. java实现红包的分配算法

    个人推测,微信红包在发出的时候已经分配好金额.比如一个10元的红包发给甲乙丙三个人,其实在红包发出去的时候,已经确定了第一个会领取多少,第二个会领取多少金额. 而不是在领取的时候才计算的.下面贴出实现 ...

  6. Nginx动静分离架构

    Nginx动静分离简单来说就将动态与静态资源分开,不能理解成只是单纯的把动态页面和静态页面物理分离,严格意义上说应该是动态请求跟静态请求分开,可以理解成使用Nginx处理静态页面,Tomcat,Res ...

  7. Python内置函数(25)——frozenset

    英文文档: class frozenset([iterable]) Return a new frozenset object, optionally with elements taken from ...

  8. 使用freemaker 导出word 含多张图片,若无图片则显示文本信息

    1.使用的Microsoft Office 2007,添加一个无边框的表格,并插入一张图片,最后另存为编码utf-8,一开始保存的word xml格式的,图片的base64编码位于文档最后,暂时没有找 ...

  9. 2.sublime设置本地远程代码同步

    1.打开编辑器输入框(Ctrl+Shift+P),并执行 2.回车后输入sftp 3.回车个后,右键项目 4.修改配置信息,保存

  10. GIT入门笔记(8)-- 查看历史提交记录/根据版本号回到过去或未来

    在Git中,用HEAD表示当前版本,也就是最新的提交版本, 上一个版本就是HEAD^, 上上一个版本就是HEAD^^, 往上100个版本写100个^比较容易数不过来,所以写成HEAD~100. Git ...