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. fetch()函数使用的一些技巧

    最近项目用到了一些es6的知识,其中大篇幅在vue框架中使用了fetch()函数,总结了一些使用的技巧: 一, 1,POST带参数)fetch提交json格式的数据到服务器: //fetch替换vue ...

  2. 测试与发布(Beta版本)

    评分基准: 按时交 - 有分(测试报告-10分,发布说明-10分,展示博客-10分),检查的项目包括后文的两个方面 测试报告(基本完成5分,根据完成质量加分,原则上不超过满分10分) 发布说明(基本完 ...

  3. Python 单向循环链表

    操作 is_empty() 判断链表是否为空 length() 返回链表的长度 travel() 遍历 add(item) 在头部添加一个节点 append(item) 在尾部添加一个节点 inser ...

  4. android头像选择(拍照,相册,裁剪)

    组织头像上传时候,不兼容android6.0,并且 imageview.setImageBitmap(BitmapFactory.decodeFile(IMAGE_FILE_LOCATION));// ...

  5. 用js 获取url 参数 页面跳转 ? 后的参数

    记得之前在原来的公司写过这个东西,但是还是忘记怎么接住参数了,只知道怎么把id传过去! 问了身边的大佬 他首先推荐了我一个链接是别人写好的方法 附上链接地址:http://blog.csdn.net/ ...

  6. 17-TypeScript代理模式

    在有些情况下,我们需要把客户端真正调用的类和方法隐藏起来,而通过暴露代理类给客户端.客户端调用代理类的方式就可以访问到真实类提供的功能. abstract class Called{ protecte ...

  7. 一个诚实的孩纸选Python的原因

    我之所以会选择python语言程序设计这门课,是因为我一开始预选选的选修课都没选上,然后在补选的时候,在别人选剩的课里面选择了python. 上了两节课之后,我发现python还挺有意思的,挺喜欢py ...

  8. 移动端300ms与点透总结

    300ms,主要发生在mobile 为啥会出现300ms延迟现象 浏览器想知道用户是否dobule tap(双击缩放) 下列情况不会出现300ms延迟 桌面浏览器 meta的viewport设置了us ...

  9. tensorflow安装篇

    安装虚拟机redhat7u4-64 镜像文件在http://www.linuxfly.org/post/659 更换yum 参考https://blog.csdn.net/xiaoyiaoyou/ar ...

  10. Android开发——发布第三方库到JitPack上

    前言: 看到大神们的写的第三方控件,比较好用,我们使用的时候直接是在gradle上加上代码就可以使用了,现在到我们写了一个第三方控件,想要别人使用的时候也是直接在gradle加上相关的代码就可以用了, ...