[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计算机上,使得这些软件 ...
 
随机推荐
- js滚动及可视区域的相关的操作
			
element.getBoundingClientRect 判断指定元素相对于页面可视窗口的位置信息,通常结合windows.onScroll方法使用,当element.getBoundingClie ...
 - 3.Linux 文件的压缩与打包
			
1.常用压缩打包命令 常用的压缩打包扩展名为如下: *.Z compress 程序压缩的文件,非常老旧了,不再细说 *.gz gzip 程序压缩的文件: *.bz2 bzip2 程序压缩的文件: *. ...
 - 国际电话区号SQL
			
CREATE TABLE `phone_prefix` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `country` varchar(30) N ...
 - Vm-Ubuntu下配置Qt开发环境
			
在昨天的Ubuntu换降下,安装Qt发现编译的时候是缺少opengl的 奈何找了好多方式都无法安装opengl 今天看到另一位大神写的,才发下自己找的还是有问题 大神帖子网址:http://blog. ...
 - Laxcus大数据管理系统2.0 (1) - 摘要和目录
			
Laxcus大数据管理系统 (version 2.0) Laxcus大数据实验室 摘要 Laxcus是Laxcus大数据实验室全体系全功能设计研发的多用户多集群大数据管理系统,支持一到百万台级节点,提 ...
 - CCS Font 知识整理总结
			
总是搞不懂 CCS 中如何正确的使用字体,这下明白了. 1.什么是 font-face font-face 顾名思义,就是文字的脸.字体是文字的外在形式,就是文字的风格,是文字的外衣.比如行书.楷书. ...
 - 一篇文章解决django中时区问题
			
首先要明确的是,当在Django项目的setting.py文件中设置了USE_TZ=True时,我们给定的时间存储到数据库的时候都会变成UTC时间(使用auto_now_add和auto_now为Tr ...
 - BZOJ 4029 HEOI2015 定价 数位贪心
			
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4029 题意概述:对于一个数字的荒谬程度定义如下:删除其所有的后缀0,然后得到的数字长度为a ...
 - URAL 1936 Roshambo(求期望)
			
Description Bootstrap: Wondering how it's played? Will: It's a game of deception. But your bet inclu ...
 - Android流式布局控件
			
1,自定义flowlayout代码 package com.hyang.administrator.studentproject.widget; import android.content.Cont ...