BZOJ_2427_[HAOI2010]软件安装_tarjan+树形DP
BZOJ_2427_[HAOI2010]软件安装_tarjan+树形DP
题意:
现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi。我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大)。
但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j)。幸运的是,一个软件最多依赖另外一个软件。如果一个软件不能正常工作,那么它能够发挥的作用为0。
我们现在知道了软件之间的依赖关系:软件i依赖软件Di。现在请你设计出一种方案,安装价值尽量大的软件。一个软件只能被安装一次,如果一个软件没有依赖则Di=0,这时只要这个软件安装了,它就能正常工作。
分析:
有环。
考虑一个环内的贡献
要么都取要么都不取
缩个点跑树形背包就可以了
代码:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 350
int head[N],to[N<<1],nxt[N<<1],cnt,n;
int m,f[N][600],cost[N],val[N],c[N],v[N],in[N];
int st[N],top,ins[N],bl[N],scc,tot,vis[N];
int dfn[N],low[N],from[N];
inline void add(int u,int v){
to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;from[cnt]=u;
}
void tarjan(int x){
st[top++]=x;
ins[x]=1;
low[x]=dfn[x]=++tot;
for(int i=head[x];i;i=nxt[i]){
if(!dfn[to[i]]){
tarjan(to[i]);
low[x]=min(low[x],low[to[i]]);
}else if(ins[to[i]]){
low[x]=min(low[x],dfn[to[i]]);
}
}
if(low[x]==dfn[x]){
int t=st[--top];ins[t]=0;
bl[t]=++scc;
c[scc]=cost[t];
v[scc]=val[t];
while(t^x){
t=st[--top];ins[t]=0;
c[scc]+=cost[t];
v[scc]+=val[t];
bl[t]=scc;
}
}
}
void dfs(int x,int y){
f[x][c[x]]=v[x];
vis[x]=1;
for(int i=head[x];i;i=nxt[i]){
if(!vis[to[i]]){
dfs(to[i],x);
for(int j=m;j>=c[x];j--){
for(int k=m-j;k>=c[to[i]];k--){
f[x][j+k]=max(f[x][j+k],f[x][j]+f[to[i]][k]);
}
}
}
}
}
int main(){
scanf("%d%d",&n,&m);
int i,j,x,y;
for(i=1;i<=n;i++)scanf("%d",&cost[i]);
for(i=1;i<=n;i++)scanf("%d",&val[i]);
for(i=1;i<=n;i++){
scanf("%d",&x);
if(x)
add(x,i);
}
for(i=1;i<=n;i++)if(!dfn[i])tarjan(i);
int tmp=cnt;
memset(head,0,sizeof(head));cnt=0;
for(i=1;i<=tmp;i++){
x=from[i],y=to[i];
if(bl[x]!=bl[y]){
add(bl[x],bl[y]);
in[bl[y]]++;
}
}
for(i=1;i<=scc;i++)if(!in[i]){
add(scc+1,i);
}
dfs(scc+1,0);
int ans=0;
for(i=0;i<=m;i++)ans=max(ans,f[scc+1][i]);
printf("%d\n",ans);
}
/*
3 10
5 5 6
2 3 4
0 1 1
*/
BZOJ_2427_[HAOI2010]软件安装_tarjan+树形DP的更多相关文章
- [BZOJ2427][HAOI2010]软件安装(tarjan+树形DP)
如果依赖关系出现环,那么对于一个环里的点,要么都选要么都不选, 所以每个环可以当成一个点,也就是强连通分量 然后就可以构造出一颗树,然后树形背包瞎搞一下就行了 注意要搞一个虚拟节点当根节点 Code ...
- HAOI2010软件安装(树形背包)
HAOI2010软件安装(树形背包) 题意 有n个物品,每个物品最多会依赖一个物品,但一个物品可以依赖于一个不独立(依赖于其它物品)的物品,且可能有多个物品依赖一个物品,并且依赖关系可能形成一个环.现 ...
- 【BZOJ2427】[HAOI2010]软件安装 Tarjan+树形背包
[BZOJ2427][HAOI2010]软件安装 Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为 ...
- 【bzoj2427】[HAOI2010]软件安装 Tarjan+树形背包dp
题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大).但是现 ...
- [HAOI2010]软件安装(树形背包,tarjan缩点)
题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是 ...
- [BZOJ2427]:[HAOI2010]软件安装(塔尖+DP)
题目传送门 题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用${W}_{i}$的磁盘空间,它的价值为${V}_{i}$.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件 ...
- BZOJ 2427: [HAOI2010]软件安装 tarjan + 树形背包
Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和 ...
- 【Luogu】P2515软件安装(树形DP)
题目链接 这么水的题我一遍没A,而且前两次提交都只有十分.气死我了.本来我的博客拒收水题来着. Tarjan缩点之后跑树形DP即可. #include<cstdio> #include&l ...
- BZOJ 2427 [HAOI2010]软件安装 | 这道树形背包裸题严谨地证明了我的菜
传送门 BZOJ 2427 题解 Tarjan把环缩成点,然后跑树形背包即可. 我用的树形背包是DFS序上搞的那种. 要注意dp数组初始化成-INF! 要注意dp顺推的时候也不要忘记看数组是否越界! ...
随机推荐
- day09_request&response学习笔记
============================================================ 一.HttpServletResponse接口 p.MsoNormal { m ...
- search for a range(找出一个数在数组中开始和结束位置)
Given an array of integers sorted in ascending order, find the starting and ending position of a giv ...
- Eclipse的优化
1. 取消系统的自动折叠 Window->Preferences-> Java->Editor->Folding: Enable folding 2. 取消按".&q ...
- 安装VirtualBox后 不能选择64bit的系统
之前在台式机上安装VirtualBox,一切OK,能够安装64位的任何版本iso包今天在hp笔记本上安装,安装VirtualBox完毕后,只能选择32位的iso版本. 而我目前只有一个linux64b ...
- json.parseArray源码解析
json.parseArray源码解析 public static <T> List<T> parseArray(String text, Class<T> cla ...
- AJAX的get和post请求原生编写方法
var xhr=new XMLHttpRequest(); xhr.onreadystatechange=function(){ if(xhr.readyState===4){ if(xhr.stat ...
- (转)java之Spring(IOC)注解装配Bean详解
java之Spring(IOC)注解装配Bean详解 在这里我们要详细说明一下利用Annotation-注解来装配Bean. 因为如果你学会了注解,你就再也不愿意去手动配置xml文件了,下面就看看 ...
- leetCode刷题(找到两个数组拼接后的中间数)
There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two ...
- QT https post请求(QNetworkRequest要设置SSL证书,而SSL证书认证有三种)
因为https访问需要用到SSL认证,而QT默认是不支持SSL认证,所以在使用之前必须先做一些准备工作: 需要安装OpenSSL库: 1.首先打开http://slproweb.com/product ...
- python3 分布式爬虫
背景 部门(东方IC.图虫)业务驱动,需要搜集大量图片资源,做数据分析,以及正版图片维权.前期主要用node做爬虫(业务比较简单,对node比较熟悉).随着业务需求的变化,大规模爬虫遇到各种问题.py ...