[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计算机上,使得这些软件 ...
随机推荐
- PostgreSQL字段名和表名大小写的问题
创建表的时候,表名和字段名必须全小写,然后查询的时候不管全大写或全小写,或是Camel模式都不会报错.只要名称中有大写字母,或者全大写,查询时就必须保证大小写正确并用双引号包起来,否则就会报“XXX不 ...
- vuex模块相互调用
https://segmentfault.com/a/1190000009434398
- 命令行下对apk签名
l创建key,需要用到keytool.exe (位于jdk安装目录\bin目录下),使用产生的key对apk签名用到的是jarsigner.exe (位于jdk安装目录\bin目录下),把上两个软件所 ...
- Laravel 5.5 创建全局公共函数
一.需求 我在使用 Laravel 进行项目逻辑处理的时候要加载一些方法,需要全局调用 这个方法又必须得是一个全局函数,因此需要给 Laravel 创建全局的公共函数 二.实现 1.创建文件 在 ap ...
- 阿里云DTS VS MySQLdump
云平台的到来,使得越来越多用户的数据库由云下迁到云上.对于这种情况,阿里对此提出两种方案,一种是MySQL自带的MySQLdump,另外一种就是阿里云的DTS. DTS支持异构数据源之间的数据迁移同步 ...
- npm无法安装全局web3的问题
- Truffle3.0集成NodeJS并完全跑通(附详细实例,可能的错误)
Truffle3.0集成NodeJS并完全跑通(附详细实例,可能的错误) Truffle3.0集成NodeJS并完全跑通(附详细实例,可能的错误) 升级到Truffle3.0 如果之前安装的是Truf ...
- HDU 4571 Travel in time(最短路径+DP)(2013 ACM-ICPC长沙赛区全国邀请赛)
Problem Description Bob gets tired of playing games, leaves Alice, and travels to Changsha alone. Yu ...
- DFS(1)——hdu1518Square
一.题目回顾 题目链接:Square 题意:给你M根木棒,请判断这些木棒能否组成正方形. 二.解题思路 DFS+剪枝 [变量说明] sum:木棒的总长度 ave:形成的正方形的边长 maxlen:最长 ...
- java多线程二之线程同步的三种方法
java多线程的难点是在:处理多个线程同步与并发运行时线程间的通信问题.java在处理线程同步时,常用方法有: 1.synchronized关键字. 2.Lock显示加锁. 3.信号量Se ...