bzoj 2427: [HAOI2010]软件安装
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
5 5 6
2 3 4
0 1 1
Sample Output
HINT
Source
由于是n个点n条边,所以是基环树森林,我们通过tarjan缩环后(环是捆绑选择的),就是森林
建立一个虚拟父亲后,就是一棵树了,然后就是经典的树型01背包问题了,但是zz选手竟然忘记树型背包了...
大致dp是这样的:f[i][j]表示i的子树花费j的体积产生的最大收益(如果选了i点就有值,不然就是0);
转移,对于以i为根的子树:
首先先不选i,然后和儿子的子树的收益进行合并:f[x][j]=max(f[x][j],f[x][k]+f[y][j-k]);
然后跟所有儿子搞完后,就来考虑选自身:
如果选不了自己的话,dp值为0,否则就直接加上(因为如果选不了i,那么i的子树中所有贡献都失效)
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
typedef long long ll;
const int N=100050;
int gi()
{
int x=0,flag=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*flag;
}
int head[N],to[N],nxt[N],v[N],w[N],low[N],dfn[N],zhan[N],vis[N],cnt,tt,sum,tot,w2[N],v2[N],fr[N];
int n,m,f[1000][1000],ru[N];
vector<int>p[N];
void lnk(int x,int y){
to[++cnt]=y,nxt[cnt]=head[x],head[x]=cnt;
}
void tarjan(int x){
low[x]=dfn[x]=++tt;vis[x]=1;zhan[++sum]=x;int y;
for(int i=head[x];i;i=nxt[i]){
y=to[i];
if(!dfn[y]){
tarjan(y);
low[x]=min(low[y],low[x]);
}
else if(vis[y]) low[x]=min(low[x],dfn[y]);
}
if(low[x]==dfn[x]){
tot++;
do{
y=zhan[sum--];vis[y]=0;
w2[tot]+=w[y];v2[tot]+=v[y];fr[y]=tot;
}while(y!=x);
}
}
void dfs(int x){
for(int i=0;i<p[x].size();i++){
int y=p[x][i];dfs(y);
for(int j=m-v2[x];j>=0;j--){
for(int k=0;k<=j;k++)
f[x][j]=max(f[x][j],f[x][k]+f[y][j-k]);
}
}
for(int i=m;i>=0;i--){
if(i>=v2[x]) f[x][i]=f[x][i-v2[x]]+w2[x];
else f[x][i]=0;
}
}
int main(){
n=gi();m=gi();int x;
for(int i=1;i<=n;i++) v[i]=gi();
for(int i=1;i<=n;i++) w[i]=gi();
for(int i=1;i<=n;i++){
x=gi();if(x!=0) lnk(i,x);
}
for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
for(int i=1;i<=n;i++)
for(int j=head[i];j;j=nxt[j]){
if(fr[i]!=fr[to[j]]) p[fr[to[j]]].push_back(fr[i]),ru[fr[i]]++;
}
int bigfa=tot+1;
for(int i=1;i<=tot;i++) if(!ru[i]) p[bigfa].push_back(i);
dfs(bigfa);printf("%d\n",f[bigfa][m]);
}
bzoj 2427: [HAOI2010]软件安装的更多相关文章
- bzoj 2427 [HAOI2010]软件安装 Tarjan缩点+树形dp
[HAOI2010]软件安装 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2029 Solved: 811[Submit][Status][Dis ...
- BZOJ 2427 [HAOI2010]软件安装 | 这道树形背包裸题严谨地证明了我的菜
传送门 BZOJ 2427 题解 Tarjan把环缩成点,然后跑树形背包即可. 我用的树形背包是DFS序上搞的那种. 要注意dp数组初始化成-INF! 要注意dp顺推的时候也不要忘记看数组是否越界! ...
- BZOJ 2427: [HAOI2010]软件安装 tarjan + 树形背包
Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和 ...
- BZOJ 2427: [HAOI2010]软件安装( dp )
软件构成了一些树和一些环, 对于环我们要不不选, 要么选整个环. 跑tarjan缩点后, 新建个root, 往每个入度为0的点(强连通分量) 连边, 然后跑树dp( 01背包 ) ---------- ...
- 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]软件安装(动态规划,Tarjan)
[BZOJ2427][HAOI2010]软件安装(动态规划,Tarjan) 题面 BZOJ 洛谷 题解 看到这类题目就应该要意识到依赖关系显然是可以成环的. 注意到这样一个性质,依赖关系最多只有一个, ...
- BZOJ_2427_[HAOI2010]软件安装_tarjan+树形DP
BZOJ_2427_[HAOI2010]软件安装_tarjan+树形DP 题意: 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁 ...
随机推荐
- 解决阿里云服务器3306端口无法访问的问题(windows server 2008r2)
3306端口一般是指mysql数据的默认端口.郁闷了几天的问题,远程无法连接服务器上的mysql服务.今天终于得到彻底解决. 首先,你要确保在服务器上安装好Mysql,并能本地启动.修改密码(如不知道 ...
- Android开发之漫漫长途 番外篇——自定义View的各种姿势2
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...
- 组合模式(Composite)
组合模式(Composite) 组合模式有时又叫部分-整体模式在处理类似树形结构的问题时比较方便,看看关系图: 直接来看代码: [java] view plaincopypublic class Tr ...
- 五十个小技巧提高PHP执行效率(一)
在项目开发过程中,经常遇到了一些PHP处理程序性能底下的情况,程序运行在centos+nginx环境,虽然这个有很多的原因如:服务器本身配置,运行环境nginx服务,php-fpm配置等等,更多有一点 ...
- angularjs 给封装的模态框元素传值,和实现兄弟传值
本例实现封装的元素所放的位置不同,而选择不同的传值,这里举例封装了bootstrap模态框,以后也方便大家去直接使用.方法举例如下:首先主页调用css/js有: <link rel=" ...
- UWP 判断系统版本
public class VersionsHelper { , ); , ); , ); , ); , ); }
- python中csv文件的读取问题
在python读取csv格式的文件时,使用csv.reader读取文件对象,出现了line contains NULL byte的错误,如下: reader = csv.reader(open(fil ...
- django模板语法之include
假如我们有以下模板index.html,代码为: <!DOCTYPE html> <html lang="en"> <head> <met ...
- MySQL基数(索引基数)
基数是数据列所包含的不同值的数量.例如,某个数据列包含值1.3.7.4.7.3,那么它的基数就是4. 索引的基数相对于数据表行数较高(也就是说,列中包含很多不同的值,重复的值很少)的时候,它的工作效果 ...
- Android酷炫有用的开源框架
一.代码库 1.from 代码家 整理比較好的源代码连接 一.兼容类库 ActionBarSherlock : Action Bar是Android 3.0后才開始支持的,ActionBarSher ...