[bzoj2427][HAOI2010]软件安装——强连通分量+树形DP
题目大意
现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi。我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大)。
但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j)。幸运的是,一个软件最多依赖另外一个软件。如果一个软件不能正常工作,那么它能够发挥的作用为0。
我们现在知道了软件之间的依赖关系:软件i依赖软件Di。现在请你设计出一种方案,安装价值尽量大的软件。一个软件只能被安装一次,如果一个软件没有依赖则Di=0,这时只要这个软件安装了,它就能正常工作。
题解
根据题目,我们建立图。
显然这个图由一些树和一些scc构成(注意:scc一定不在树上),那么我们可以知道,如果选了scc中的一个点,其他点必须也要选,所以我们把所有的scc缩成一个点,这样就构成了一个森林。
对于一个入度为0的点,我们从一个虚点向其连接一条边,这样图就变成了树。
考虑树形dp,定义f[i][j]为对于i为根的子树总共分配j点权值能拿到的最大value
我们可以有$$f[i][j] = f[k][l] + f[i][j-l]$$
记忆化搜索即可。
代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxn = 505;
const ll maxm = 1000;
ll n, m, K, s, ans = 0;
ll w[maxn], v[maxn], W[maxn], V[maxn];
ll cnt[maxn], vis[maxn], in[maxn], f[maxn][maxm];
vector<ll> sc[maxn];
vector<ll> vs;
vector<ll> G[maxn];
vector<ll> rg[maxn];
vector<ll> ng[maxn];
void add(ll from, ll to) {
G[from].push_back(to);
rg[to].push_back(from);
}
void add_edge(ll from, ll to) {
in[to] = 1;
ng[from].push_back(to);
}
void dfs(ll s) {
vis[s] = 1;
for (ll i = 0; i < G[s].size(); i++) {
if (!vis[G[s][i]])
dfs(G[s][i]);
}
vs.push_back(s);
}
void rdfs(ll s, ll k) {
vis[s] = 1;
for (ll i = 0; i < rg[s].size(); i++) {
if (!vis[rg[s][i]])
rdfs(rg[s][i], k);
}
cnt[s] = k;
sc[k].push_back(s);
}
void scc() {
memset(vis, 0, sizeof(vis));
vs.clear();
for (ll i = 1; i <= n; i++) {
if (!vis[i])
dfs(i);
}
ll k = 0;
memset(vis, 0, sizeof(vis));
for (ll i = vs.size() - 1; i >= 0; i--) {
if (!vis[vs[i]])
rdfs(vs[i], k++);
}
K = k;
}
void build_graph() {
for (ll i = 0; i < K; i++) {
for (ll j = 0; j < sc[i].size(); j++) {
W[i] += w[sc[i][j]];
V[i] += v[sc[i][j]];
}
}
for (ll i = 1; i <= n; i++) {
for (ll j = 0; j < G[i].size(); j++) {
if (cnt[i] != cnt[G[i][j]])
add_edge(cnt[i], cnt[G[i][j]]);
}
}
s = K + 1;
for (ll i = 0; i < K; i++)
if (!in[i])
add_edge(s, i);
}
void dp(ll x) {
for (ll i = 0; i < ng[x].size(); i++) {
dp(ng[x][i]);
for (ll j = m - W[x]; j >= 0; j--) { //鏋氫妇閫夊畬鑷繁鍚庤垂鐢?
for (ll k = 0; k <= j; k++) { //鏋氫妇缁欏効瀛愮殑璐圭敤
f[x][j] = max(f[x][j], f[x][k] + f[ng[x][i]][j - k]);
}
}
}
for (ll j = m; j >= 0; j--) {
if (j >= W[x])
f[x][j] = f[x][j - W[x]] + V[x];
else
f[x][j] = 0;
}
}
int main() {
// freopen("input", "r", stdin);
scanf("%lld %lld", &n, &m);
for (ll i = 1; i <= n; i++)
scanf("%lld", &w[i]);
for (ll i = 1; i <= n; i++)
scanf("%lld", &v[i]);
for (ll i = 1; i <= n; i++) {
ll x;
scanf("%lld", &x);
if (x)
add(x, i);
}
scc();
build_graph();
dp(s);
printf("%lld\n", f[s][m]);
}
[bzoj2427][HAOI2010]软件安装——强连通分量+树形DP的更多相关文章
- bzoj2427 [HAOI2010]软件安装——缩点+树形DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2427 今天的考试题...好不容易一次写对了树形DP,却没发现有环的情况... 发现自己 ta ...
- BZOJ 2427 软件安装(强连通分量+树形背包)
题意:现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大).但是现在有 ...
- 洛谷 P2515 [HAOI2010]软件安装(缩点+树形dp)
题面 luogu 题解 缩点+树形dp 依赖关系可以看作有向边 因为有环,先缩点 缩点后,有可能图不联通. 我们可以新建一个结点连接每个联通块. 然后就是树形dp了 Code #include< ...
- bzoj 2427: [HAOI2010]软件安装【tarjan+树形dp】
一眼最大权闭合子图,然后开始构图,画了画之后发现我其实是个智障网络流满足不了m,于是发现正确的打开方式应该是一眼树上dp 然后仔细看了看性质,发现把依赖关系建成图之后是个奇环森林,这个显然不能直接dp ...
- [BZOJ2427][HAOI2010]软件安装(Tarjan+DP)
2427: [HAOI2010]软件安装 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1987 Solved: 791[Submit][Statu ...
- bzoj2427:[HAOI2010]软件安装(Tarjan+tree_dp)
2427: [HAOI2010]软件安装 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1053 Solved: 424[Submit][Statu ...
- BZOJ2427:[HAOI2010]软件安装(树形DP,强连通分量)
Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和 ...
- [BZOJ2427][HAOI2010]软件安装(tarjan+树形DP)
如果依赖关系出现环,那么对于一个环里的点,要么都选要么都不选, 所以每个环可以当成一个点,也就是强连通分量 然后就可以构造出一颗树,然后树形背包瞎搞一下就行了 注意要搞一个虚拟节点当根节点 Code ...
- [BZOJ2427]:[HAOI2010]软件安装(塔尖+DP)
题目传送门 题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用${W}_{i}$的磁盘空间,它的价值为${V}_{i}$.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件 ...
随机推荐
- android中activity,window,view之间的关系
activity:控制单元 window:承载模型 view:显示视图 几个小tip: 1.一个 Activity 构造的时候一定会构造一个 Window(PhoneWindow),并且只有一个 2. ...
- cachel-control
nodejs: res.set('Cache-Control', 'public, max-age=31557600'); express全局设置: app.use(express.sta ...
- 「日常训练」 Finite or not? (CFR483D2C)
题意(Codeforces 984C) 给定p,q,b" role="presentation">p,q,bp,q,b,问pq" role="p ...
- Qt程序加图标
第一步 准备一个ICON图标 例如:myicon.ico 新建文本文件,里面编辑文字 IDI_ICON1 ICON DISCARDABLE "myicon.ico" 文件另存为 x ...
- 深挖 NGUI 基础 之UIRoot (一)
当你开始使用NGUI的时候,简单的从项目视图 中一个”Control”预设体 拖拽到场景视图中,你将会发现 Hierarchy层次面板中会出现以下层次结构: 其中 UI Root作为根节点,是每个NG ...
- shiro笔记
控制某一角色拥有此选项 上图 标签为shiro:hasRole表示 此时只有admin角色才拥有 系统用户管理和角色管理两个tab 页 上图 标签为shiro:hasPermission表示 此时只有 ...
- 07-Mysql数据库----数据类型
介绍 存储引擎决定了表的类型,而表内存放的数据也要有不同的类型,每种数据类型都有自己的宽度,但宽度是可选的 详细参考链接:http://www.runoob.com/mysql/mysql-data- ...
- sphinx调用API参考(官方手册)
API的参考实现是用PHP写成的,因为(我们相信)较之其他语言,Sphinx在PHP中应用最广泛.因此这份参考文档基于PHP API的参考,而且这节中的所有的代码样例都用PHP给出. 当然,其他所有A ...
- LeetCode - 67. Add Binary(4ms)
Given two binary strings, return their sum (also a binary string). The input strings are both non-em ...
- penLDAP学习笔记
LDAP协议 目录是一组具有类似属性.以一定逻辑和层次组合的信息.常见的例子是通讯簿,由以字母顺序排列的名字.地址和电话号码组成.目录服务是一种在分布式环境中发现目标的方法.目录具有两个主要组成部分: ...