洛谷 P2515 [HAOI2010]软件安装 解题报告
P2515 [HAOI2010]软件安装
题目描述
现在我们的手头有\(N\)个软件,对于一个软件\(i\),它要占用\(W_i\)的磁盘空间,它的价值为\(V_i\)。我们希望从中选择一些软件安装到一台磁盘容量为\(M\)计算机上,使得这些软件的价值尽可能大(即\(V_i\)的和最大)。
但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件\(j\)(包括软件\(j\)的直接或间接依赖)的情况下才能正确工作(软件\(i\)依赖软件\(j\))。幸运的是,一个软件最多依赖另外一个软件。如果一个软件不能正常工作,那么它能够发挥的作用为0。
我们现在知道了软件之间的依赖关系:软件\(i\)依赖软件\(D_i\)。现在请你设计出一种方案,安装价值尽量大的软件。一个软件只能被安装一次,如果一个软件没有依赖则\(D_i=0\),这时只要这个软件安装了,它就能正常工作。
输入输出格式
输入格式:
第1行:\(N,M\) \((0<=N<=100,0<=M<=500)\)
第2行:\(W_1,W_2,...W_i,...,W_n\) \((0<=W_i<=M)\)
第3行:\(V_1, V_2, ..., V_i, ..., V_n\) \((0<=V_i<=1000)\)
第4行:\(D_1, D_2, ..., D_i, ..., D_n\) \((0<=D_i<=N, D_i≠i)\)
输出格式:
一个整数,代表最大价值
咋一看十分的像背包,但里面的东西互相拧成一坨相互依赖之类的,我们需要稍微简化一下问题。
一个软件最多依赖另外一个软件,把被别人依赖的某个软件向依赖它的软件连上一条有向边,可以得出,每个点的入度均为1,这是啥?一棵树啊。
然而这样想就出现了问题,万一有环呢?好说,把环给缩掉就行了。我们把新出现的一个森林连上一个共同的虚根0,构成一颗树,于是问题就转换成了树形DP
需要注意的是,一个点要用它子树,当且仅当这个子树的根被选上时才可用。
\(dp[i][j]\)代表以\(i\)为根的树,在容量为\(j\)的时候,没有处理它的根,所得到的最大价值。
转移:\(dp[i][j]=max(dp[i][j],dp[i-k][j]+dp[son][k-w[son]]+v[son])\)
#include <cstdio>
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
const int N=104;
const int M=502;
struct Edge
{
int to,next;
}edge[N];
int head[N],cnt=0;
void add(int u,int v)
{
edge[++cnt].next=head[u];edge[cnt].to=v;head[u]=cnt;
}
int n,m,w[N],v[N];
int time=0,low[N],dfn[N],vis[N],s[N],tot=0,ha[N];
int n0=0,w0[N],v0[N],in[N],g[N][N];
void tarjan(int now)
{
low[now]=dfn[now]=++time;
s[++tot]=now;
vis[now]=1;
for(int i=head[now];i;i=edge[i].next)
{
int v=edge[i].to;
if(!dfn[v])
{
tarjan(v);
low[now]=min(low[now],low[v]);
}
else if(vis[v])
low[now]=min(low[now],dfn[v]);
}
if(dfn[now]==low[now])
{
int k;n0++;
do
{
k=s[tot--];
vis[k]=0;
ha[k]=n0;
w0[n0]+=w[k];
v0[n0]+=v[k];
}while(k!=now);
}
}
int dp[N][M];//以i为根(不装)的子树装j时的最大价值
void dfs(int now)
{
for(int i=1;i<=n0;i++)
if(g[now][i])
{
dfs(i);
for(int j=m;j>=w0[i];j--)
for(int k=w0[i];k<=j;k++)
dp[now][j]=max(dp[now][j],dp[i][k-w0[i]]+v0[i]+dp[now][j-k]);
}
}
int main()
{
scanf("%d%d",&n,&m);int to;
for(int i=1;i<=n;i++) scanf("%d",w+i);
for(int i=1;i<=n;i++) scanf("%d",v+i);
for(int i=1;i<=n;i++) {scanf("%d",&to);if(to) add(to,i);}
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=edge[j].next)
{
int v=edge[j].to;
if(ha[i]!=ha[v]&&!g[ha[i]][ha[v]])
g[ha[i]][ha[v]]=1,in[ha[v]]++;
}
for(int i=1;i<=n0;i++)
if(!in[i]) g[0][i]=1;;
dfs(0);
printf("%d\n",dp[0][m]);
return 0;
}
2018.6.13
洛谷 P2515 [HAOI2010]软件安装 解题报告的更多相关文章
- 洛谷—— P2515 [HAOI2010]软件安装
题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是 ...
- 洛谷 P2515 [HAOI2010]软件安装
题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是 ...
- 洛谷——P2515 [HAOI2010]软件安装
https://www.luogu.org/problem/show?pid=2515#sub 题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中 ...
- 洛谷 P2515 [HAOI2010]软件安装(缩点+树形dp)
题面 luogu 题解 缩点+树形dp 依赖关系可以看作有向边 因为有环,先缩点 缩点后,有可能图不联通. 我们可以新建一个结点连接每个联通块. 然后就是树形dp了 Code #include< ...
- 洛谷P2515 [HAOI2010]软件安装(tarjan缩点+树形dp)
传送门 我们可以把每一个$d$看做它的父亲,这样这个东西就构成了一个树形结构 问题是他有可能形成环,所以我们还需要一遍tarjan缩点 缩完点后从0向所有入度为零的点连边 然后再跑一下树形dp就行了 ...
- 洛谷_Cx的故事_解题报告_第四题70
1.并查集求最小生成树 Code: #include <stdio.h> #include <stdlib.h> struct node { long x,y,c; ...
- 洛谷 P2317 [HNOI2005]星际贸易 解题报告
P2317 [HNOI2005]星际贸易 题目描述 输入输出格式 输入格式: 输出格式: 如果可以找到这样的方案,那么输出文件output.txt中包含两个整数X和Y.X表示贸易额,Y表示净利润并且两 ...
- 洛谷 P3802 小魔女帕琪 解题报告
P3802 小魔女帕琪 题目背景 从前有一个聪明的小魔女帕琪,兴趣是狩猎吸血鬼. 帕琪能熟练使用七种属性(金.木.水.火.土.日.月)的魔法,除了能使用这么多种属性魔法外,她还能将两种以上属性组合,从 ...
- 洛谷 P2606 [ZJOI2010]排列计数 解题报告
P2606 [ZJOI2010]排列计数 题目描述 称一个\(1,2,...,N\)的排列\(P_1,P_2...,P_n\)是\(Magic\)的,当且仅当对所以的\(2<=i<=N\) ...
随机推荐
- 身在上海的她,该不该继续"坚持"前端开发?
作者:13 GitHub:https://github.com/ZHENFENG13 版权声明:本文为原创文章,未经允许不得转载. 一 对于目前的IT行业,我实在不想她还没在这个行业中站稳脚跟就开始有 ...
- linux下expect环境安装以及简单脚本测试
expect是交互性很强的脚本语言,可以帮助运维人员实现批量管理成千上百台服务器操作,是一款很实用的批量部署工具!expect依赖于tcl,而linux系统里一般不自带安装tcl,所以需要手动安装 下 ...
- cf946d 怎样逃最多的课dp
来源:codeforces D. Timetable Ivan is a student at Berland ...
- Linux内核及分析 第八周 进程的切换和系统的一般执行过程
学习笔记: 一.进程调度与进程调度的时机分析 1.不同类型的进程有不同需求的调度需求: 第一种分类: —I/O-bound:频繁的进行I/O,通常会花费很多时间等待I/O操作的完成 —CPU-boun ...
- 素数问题练习_HDOJ1262
HDOJ1262_寻找素数对 和上一篇博客一样的解法,将10000以内的所有素数求出即可解题. #include<stdio.h> #include<stdlib.h> #in ...
- Linux shell 菜鸟学习笔记....
20171123 Linux shell 基础学习笔记1. shell 的开始 一般是 #!/bin/bash 通过 #! 来唯一指定使用的shell路径 其他的 # 都表示注释.2. shell 的 ...
- MongoDb在windows10下的安装、创建用户和数据库
1.mongodb下载地址https://www.mongodb.com/download-center#community 2.安装 3.在D:\MongoDB目录下创建db和log两个文件夹 ...
- Jquery Jquery对象和DOM对象的微妙联系
声明变量 var $variable= Jquery 对象: var varibake= DOM对象: var $cr= $("#id&q ...
- 转《ionic生命周期》
1.认识ionic的生命周期钩子 截至ionic 3.8.0版本,框架提供了8个钩子函数,它们分别会在页面生命周期的各个阶段被触发,我们来简单了解一下. 1.1 ionViewDidLoad 页面加载 ...
- python有序字典
最近的django开发中用到了有序字典,所以研究了一下,以下. 示例: 有序字典和通常字典类似,只是它可以记录元素插入其中的顺序,而一般字典是会以任意的顺序迭代的. 普通字典: d1={} d1['a ...