【BZOJ2427】[HAOI2010]软件安装 Tarjan+树形背包
【BZOJ2427】[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
题解:n个点n条边,所以依赖关系一定会出现环,环中的要么都取要么都不取,那么Tarjan缩环将环变成一个物品即可。然后原图就变成了森林,新建0号点将所有树根连起来然后跑树形背包即可。
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int n,m,tot,sum,top,cnt,ans;
int w[110],v[110],d[110],dep[110],low[110],ins[110],sta[110],bel[110],W[110],V[110],D[110];
int to[110],next[110],head[110],f[110][510],vis[110];
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
void tarjan(int x)
{
dep[x]=low[x]=++tot;
ins[x]=1,sta[++top]=x;
if(d[x])
{
if(!dep[d[x]]) tarjan(d[x]),low[x]=min(low[x],low[d[x]]);
else if(ins[d[x]]) low[x]=min(low[x],dep[d[x]]);
}
if(dep[x]==low[x])
{
int t;
sum++;
do
{
t=sta[top--],bel[t]=sum,W[sum]+=w[t],V[sum]+=v[t],ins[t]=0;
}while(t!=x);
}
}
void add(int a,int b)
{
to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
}
void dfs(int x)
{
int i,j,k;
for(i=0;i<W[x];i++) f[x][i]=-1<<29;
f[x][W[x]]=V[x];
for(i=head[x];i!=-1;i=next[i])
{
dfs(to[i]);
for(j=m;j>=W[x]+W[to[i]];j--) for(k=W[to[i]];k<=j-W[x];k++)
f[x][j]=max(f[x][j],f[x][j-k]+f[to[i]][k]);
}
}
int main()
{
n=rd(),m=rd();
int i;
for(i=1;i<=n;i++) w[i]=rd();
for(i=1;i<=n;i++) v[i]=rd();
for(i=1;i<=n;i++) d[i]=rd();
for(i=1;i<=n;i++) if(!dep[i]) tarjan(i);
memset(head,-1,sizeof(head));
for(i=1;i<=n;i++) if(bel[d[i]]!=bel[i]) vis[bel[i]]=1,add(bel[d[i]],bel[i]);
for(i=1;i<=sum;i++) if(!vis[i]) add(0,i);
dfs(0);
for(i=0;i<=m;i++) ans=max(ans,f[0][i]);
printf("%d",ans);
return 0;
}
【BZOJ2427】[HAOI2010]软件安装 Tarjan+树形背包的更多相关文章
- BZOJ2427: [HAOI2010]软件安装 tarjan+树形背包
分析: 一开始我以为是裸的树形背包...之后被告知这东西...可能有环...什么!有环! 有环就搞掉就就可以了...tarjan缩点...建图记得建立从i到d[i]之后跑tarjan,因为这样才能判断 ...
- 【bzoj2427】[HAOI2010]软件安装 Tarjan+树形背包dp
题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大).但是现 ...
- BZOJ 2427: [HAOI2010]软件安装 tarjan + 树形背包
Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和 ...
- [BZOJ2427][HAOI2010]软件安装(tarjan+树形DP)
如果依赖关系出现环,那么对于一个环里的点,要么都选要么都不选, 所以每个环可以当成一个点,也就是强连通分量 然后就可以构造出一颗树,然后树形背包瞎搞一下就行了 注意要搞一个虚拟节点当根节点 Code ...
- 【BZOJ-2427】软件安装 Tarjan + 树形01背包
2427: [HAOI2010]软件安装 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 960 Solved: 380[Submit][Status ...
- [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 ...
- HAOI2010软件安装(树形背包)
HAOI2010软件安装(树形背包) 题意 有n个物品,每个物品最多会依赖一个物品,但一个物品可以依赖于一个不独立(依赖于其它物品)的物品,且可能有多个物品依赖一个物品,并且依赖关系可能形成一个环.现 ...
- [HAOI2010]软件安装(树形背包,tarjan缩点)
题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是 ...
随机推荐
- 关于centos防火墙
Centos升级到7之后,内置的防火墙已经从iptables变成了firewalld Centos7默认安装了firewalld,如果没有安装的话,可以使用 yum install firewalld ...
- 【WEB基础】HTML & CSS 基础入门(8)表单
前面 前面我们已经熟悉了网页上一些常见的元素,如在网页上显示一段文字.一张图片.一个列表.一张表格等等.这些东西都是事先编辑好显示在页面上只提供给用户看的,实际上,我们可以把这样的页面称之为静态页面. ...
- BZOJ 3029 守卫者的挑战
题面 Description 打开了黑魔法师Vani的大门,队员们在迷宫般的路上漫无目的地搜寻着关押applepi的监狱的所在地.突然,眼前一道亮光闪过."我,Nizem,是黑魔法圣殿的守卫 ...
- linux grep 搜索查找
查找关键字在哪些文件夹中的哪些文件中出现(只列出文件名称): grep -l 15386257298 */* 查找关键字在哪些文件夹中的哪些文件中出现(列出文件名称+关键字): grep -o 153 ...
- SuperIndicator 一个专用打造轮播的类库
Github地址:https://github.com/hejunlin2013/SuperIndicator,欢迎fork,star.著名Android-Universal-Image-Loader ...
- Android内存泄露自动检测神器LeakCanary
经典的面试题: a.怎样在coding过程中避免内存泄露? b.怎样检测内存泄露? 这两个问题我想大部分Android 职位面试时都会被问到吧. 怎样避免就不赘述了,网上很多答案. 工具呢,当然也有很 ...
- vue2.0中怎么获取元素
在元素上添加 v-el:food-wrapper (不用驼峰的写法) vue1版本 报错: vue2版本 (vue2把vue1中的 v-el 改为了 ref vue1 v-el:foods-wrapp ...
- Android 网络编程 记录
简单介绍 看了深入理解Android网络编程感觉不错.今天对Android网络编程进行了要点记录. 内容 Android基于网络技术和编程实践 要点 定义 描写叙述 IP协议 用于报文交换网络的一种面 ...
- JavaScript中给二维数组动态添加元素的质朴方法
var myData = new Array(); for(var i=0;i<tableDatas.length;i++){ var arr=tableDatas[i]; ...... /// ...
- 百科知识 国内的创业项目如何众筹,能登录Kickstarter吗
一个国内的团队登陆Kickstarter到底有多难? 300万用户,4.8亿美元筹款,Kickstarter在2013年交出了一份惊艳的答卷.对于美英澳加新荷六国的创业团队来说,Kickstarter ...