【洛谷P2515】[HAOI2010]软件安装

题目描述

现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi。我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大)。

但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j)。幸运的是,一个软件最多依赖另外一个软件。如果一个软件不能正常工作,那么它能够发挥的作用为0。

我们现在知道了软件之间的依赖关系:软件i依赖软件Di。现在请你设计出一种方案,安装价值尽量大的软件。一个软件只能被安装一次,如果一个软件没有依赖则Di=0,这时只要这个软件安装了,它就能正常工作。

Tarjan+树形背包。

Tarjan就是为了恶心人的,注意建边。

模了第一篇题解大佬的奇淫技巧,对于fa是0的点,可以不去管它,等到缩完点重新建边之后,我们统计每个点的入度,如果该点入度为零,那么说明这个点是森林中一棵树的树根,那么这个时候我们再建立超级源点就可以了。

不然的话再所点之前建立超级源点真的恶心,深受其害。。。

至于树形DP,这道题和选课基本上一样,不过我发现了一种更好的有依赖的树形DP的写法,也算是现在才真正学会。

模板:

code:

void dfs(int u){
for(int i=w[u];i<=n;i++)f[u][i]=v[u];
for(int i=head[i];i;i=edge[i].nxt){
int v=edge[i].to;
dfs(v);
for(int j=m;j>=w[u];j--){
for(int k=0;k<=j-w[u];k++){
f[u][j]=max(f[u][j],f[u][j-k]+f[v][k]);
}
}
}
}

code:

#include <iostream>
#include <cstdio> using namespace std; const int wx=1017; inline int read(){
int sum=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0';ch=getchar();}
return sum*f;
} int num1,num2,n,m,top,tot,col;
int head1[wx],head2[wx],dfn[wx],low[wx],st[wx];
int belong[wx],f[wx][wx],tmp[wx];
int w[wx],v[wx],W[wx],V[wx],fa[wx]; struct node{
int nxt,to;
}edge1[wx*2]; struct e{
int nxt,to;
}edge2[wx*2]; void add1(int from,int to){
edge1[++num1].nxt=head1[from];
edge1[num1].to=to;
head1[from]=num1;
} void add2(int from,int to){
edge2[++num2].nxt=head2[from];
edge2[num2].to=to;
head2[from]=num2;
} void Tarjan(int u){
dfn[u]=low[u]=++tot;
st[++top]=u;
for(int i=head1[u];i;i=edge1[i].nxt){
int v=edge1[i].to;
if(!dfn[v]){
Tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(!belong[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
belong[u]=++col;
while(st[top]!=u){
belong[st[top]]=col;
top--;
}
top--;
}
} void CQ(){
for(int i=1;i<=n;i++){
if(belong[i]!=belong[fa[i]]&&fa[i]){
add2(belong[fa[i]],belong[i]);
tmp[belong[i]]++;
}
}
for(int i=1;i<=n;i++){
W[belong[i]]+=w[i];
V[belong[i]]+=v[i];
}
for(int i=1;i<=col;i++){
if(!tmp[i])add2(col+1,i);
}
} void dfs(int u){
for(int i=W[u];i<=m;i++)f[u][i]=V[u];
for(int i=head2[u];i;i=edge2[i].nxt){
int v=edge2[i].to;
dfs(v);
for(int j=m;j>=W[u];j--){
for(int k=0;k<=j-W[u];k++){
f[u][j]=max(f[u][j],f[u][j-k]+f[v][k]);
}
}
}
} int main(){
n=read();m=read();
for(int i=1;i<=n;i++)w[i]=read();
for(int i=1;i<=n;i++)v[i]=read();
for(int i=1;i<=n;i++){
fa[i]=read();
if(!fa[i])continue;
add1(fa[i],i);
}
for(int i=1;i<=n;i++)if(!dfn[i])Tarjan(i);
CQ();
dfs(col+1);
printf("%d\n",f[col+1][m]);
return 0;
}

Tarjan+树形DP【洛谷P2515】[HAOI2010]软件安装的更多相关文章

  1. 洛谷 P2515 [HAOI2010]软件安装 解题报告

    P2515 [HAOI2010]软件安装 题目描述 现在我们的手头有\(N\)个软件,对于一个软件\(i\),它要占用\(W_i\)的磁盘空间,它的价值为\(V_i\).我们希望从中选择一些软件安装到 ...

  2. 洛谷P2515 [HAOI2010]软件安装(tarjan缩点+树形dp)

    传送门 我们可以把每一个$d$看做它的父亲,这样这个东西就构成了一个树形结构 问题是他有可能形成环,所以我们还需要一遍tarjan缩点 缩完点后从0向所有入度为零的点连边 然后再跑一下树形dp就行了 ...

  3. 洛谷 P2515 [HAOI2010]软件安装(缩点+树形dp)

    题面 luogu 题解 缩点+树形dp 依赖关系可以看作有向边 因为有环,先缩点 缩点后,有可能图不联通. 我们可以新建一个结点连接每个联通块. 然后就是树形dp了 Code #include< ...

  4. 洛谷—— P2515 [HAOI2010]软件安装

    题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是 ...

  5. 洛谷 P2515 [HAOI2010]软件安装

    题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是 ...

  6. 洛谷——P2515 [HAOI2010]软件安装

    https://www.luogu.org/problem/show?pid=2515#sub 题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中 ...

  7. 树形DP 洛谷P2014 选课

    洛谷P2014 选课 题目描述 在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习.现在有N门功课,每门 ...

  8. luogu P2515 [HAOI2010]软件安装 |Tarjan+树上背包

    题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为MM计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但 ...

  9. [bzoj2427]P2515 [HAOI2010]软件安装(树上背包)

    tarjan+树上背包 题目描述 现在我们的手头有 \(N\) 个软件,对于一个软件 \(i\),它要占用 \(W_i\) 的磁盘空间,它的价值为 \(V_i\).我们希望从中选择一些软件安装到一台磁 ...

  10. P2515 [HAOI2010]软件安装

    树形背包 #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> ...

随机推荐

  1. 侯捷STL学习(四)--OOP-GP/操作符重载-泛化特化

    C++标准库第二讲 体系结构与内核分析 第1-7节为第一讲 读源代码前的准备 第八节:源代码分布 C++基本语法 模板的使用 数据结构和算法 本课程主要使用:Gnu C 2.9.1与Gun C 4.9 ...

  2. MySQL启动失败解决办法

    本人大二,进了一家培训机构学了两年,然后跟着他们做项目,其实也是练习,然后过程中遇到好多错误,当时解决了,然后下次遇到又忘了,-_-!  -_-||| 我就想通过写博客来记载一下我遇到的错误和解决的办 ...

  3. redis学习一 大体概述

    redis 命令查找:http://doc.redisfans.com/ 1,redis 技术简介以及疑问      redis是一个开源的,内存存储的数据结构服务器.可以用做数据库,高速缓存和消息队 ...

  4. 用命令查看端口占用情况 netstat -ano

    查看所有端口 netstat -ano 可以看到进程ID 参考某个具体端口,第五列就是PID进程ID了. netstat -aon|findstr "80"

  5. FFmpeg for Android compiled with x264, libass, fontconfig, freetype and fribidi

    android下打算使用ffmpeg的 drawtext ,不过需要 --enable-libfreetype  但是freetype是个第三方库,所以需要先编译freetype,然后再编译ffmpe ...

  6. 201671010127 2016—2017—2 Java学习周结

    时间真是个最公平东西,只要能够好好地利用它,它可以为我们带来我们我们所想要的东西.学习Java已经有一周了,对于Java基础知识的认识也更进一步,对Java的兴趣也愈来愈浓.实现一个Java程序,主要 ...

  7. dos 下bat命令

    注:cmd下    help > result.txt assoc 显示或修改文件扩展名关联. attrib 显示或更改文件属性. break 设置或清除扩展式 ctrl+c 检查. bcded ...

  8. 猪羊——HTML解析

    HTML标签和属性大全见:http://www.cnblogs.com/Mr-liyang/p/5797976.html CSS样式大全:http://www.cnblogs.com/Mr-liyan ...

  9. C++中的纯虚函数和虚函数的作用

    1. 虚函数和纯虚函数可以定义在同一个类(class)中,含有纯虚函数的类被称为抽象类(abstract class),而只含有虚函数的类(class)不能被称为抽象类(abstract class) ...

  10. python2 and python3 difference - division

    1. python2 2. python3 3.from python environment import py3 features