题目描述

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

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

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

输入输出格式

输入格式:

第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 )

输出格式:

一个整数,代表最大价值

输入输出样例

输入样例#1:

3 10
5 5 6
2 3 4
0 1 1
输出样例#1:

5

Tarjan缩点+树形dp

屠龙宝刀点击就送

#include <ctype.h>
#include <cstdio>
#define N 605 void read(int &x)
{
x=;bool f=;
char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=;ch=getchar();}
while(isdigit(ch)) {x=x*+ch-'';ch=getchar();}
x=f?(~x)+:x;
}
struct node
{
int next,to;
}edge[N<<];
struct node2
{
int next,to;
}edge2[N<<];
struct thing
{
int v,w;
}th[N];
bool in[N],instack[N];
int head2[N],cnt2,f[N][N],w[N],v[N],stack[N],top,n,m,head[N],cnt,sumcol,col[N],dfn[N],low[N],tim;
void add(int u,int v)
{
edge[++cnt].next=head[u];
edge[cnt].to=v;
head[u]=cnt;
}
int min(int a,int b){return a>b?b:a;}
int max(int a,int b){return a>b?a:b;}
void tarjan(int x)
{
dfn[x]=low[x]=++tim;
instack[x]=;
stack[++top]=x;
for(int i=head[x];i;i=edge[i].next)
{
int v=edge[i].to;
if(instack[v]) low[x]=min(low[x],dfn[v]);
if(!dfn[v]) tarjan(v),low[x]=min(low[x],low[v]);
}
if(low[x]==dfn[x])
{
int t;
sumcol++;
do
{
t=stack[top--];
instack[t]=false;
col[t]=sumcol;
th[sumcol].v+=v[t];
th[sumcol].w+=w[t];
}while(t!=x);
}
}
void dp(int x)//此处DP为树上01背包 
{
for(int i=head2[x];i;i=edge2[i].next)
{
dp(edge2[i].to);//延伸的点继续dp
for(int j=m-th[x].w;j>=;j--)
{
for(int k=;k<=j;k++) f[x][j]=max(f[x][j],f[x][k]+f[edge2[i].to][j-k]);
}
}
for(int j=m;j>=;j--)
{
if(j>=th[x].w) f[x][j]=f[x][j-th[x].w]+th[x].v;
else f[x][j]=;
}
}
void add2(int u,int v)
{
edge2[++cnt2].next=head2[u];
edge2[cnt2].to=v;
head2[u]=cnt2;
}
void rebuild()
{
for(int i=;i<=n;i++)
{
for(int j=head[i];j;j=edge[j].next)
{
int v=edge[j].to;
if(col[v]!=col[i])
{
in[col[v]]=;
add2(col[i],col[v]);
}
}
}
}
int main()
{
read(n);read(m);
for(int i=;i<=n;i++) read(w[i]);
for(int i=;i<=n;i++) read(v[i]);
for(int x,i=;i<=n;i++)
{
read(x);
if(x) add(x,i);
}
for(int i=;i<=n;i++) if(!dfn[i]) tarjan(i);
rebuild();
for(int i=;i<=sumcol;i++)
{
if(!in[i])
{
in[i]=;
add2(sumcol+,i);
}
}
dp(sumcol+);
printf("%d",f[sumcol+][m]);
return ;
}

洛谷 P2515 [HAOI2010]软件安装的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. P2515 [HAOI2010]软件安装

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

  9. luogu P2515 [HAOI2010]软件安装

    传送门 看到唯一的依赖关系,容易想到树型dp,即\(f_{i,j}\)表示选点\(i\)及子树内连通的点,代价为\(j\)的最大价值,然后就是选课那道题 但是要注意 1.题目中的依赖关系不一定是树,可 ...

随机推荐

  1. [USACO 2016Dec] Team Building

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=4742 [算法] 动态规划 用Fi,j,k表示约翰的前i头牛和保罗的前j头牛匹配 , ...

  2. 【前端】CentOS 7 系列教程之四: 配置 git 服务器自动部署

    转载请注明出处:http://www.cnblogs.com/shamoyuu/p/linux_4.html 安装pm2守护进程,备用 npm install -g pm2 创建/srv/www文件夹 ...

  3. linux设备驱动第三篇:如何实现一个简单的字符设备驱动

    在linux设备驱动第一篇:设备驱动程序简介中简单介绍了字符驱动,本篇简单介绍如何写一个简单的字符设备驱动.本篇借鉴LDD中的源码,实现一个与硬件设备无关的字符设备驱动,仅仅操作从内核中分配的一些内存 ...

  4. eclipse导入工程报Invalid project description(转载)

    转自:http://blog.sina.com.cn/s/blog_a2eab3000101k3r7.html 昨天新搭建的环境,今天把以前的项目导入eclipse时报错: 说的是我导入的项目与wor ...

  5. SCUT - 249 - Hello World - 数位dp

    https://scut.online/p/249 数位dp的模板题? 需要特殊判断0,这个很不优雅,因为0-1=-1是个很奇葩的东西? #include<bits/stdc++.h> u ...

  6. PTA 模拟【string以及字母->数组下标】

    假设有九宫格输入法键盘布局如下: [ 1,.?! ] [ 2ABC ] [ 3DEF ] [ 4GHI ] [ 5JKL ] [ 6MNO ] [ 7PQRS ] [ 8TUV ] [ 9WXYZ ] ...

  7. bzoj 5496: [2019省队联测]字符串问题【SAM+拓扑】

    有一个想法就是暴力建图,把每个A向有和他相连的B前缀的A,然后拓扑一下,这样的图是n^2的: 考虑优化建图,因为大部分数据结构都是处理后缀的,所以把串反过来,题目中要求的前缀B就变成了后缀B 建立SA ...

  8. 报错org.springframework.dao.DataIntegrityViolationException

    最简单的原因可能是数据库外键字段选择了不能为空, 改为允许为空就行了.

  9. 编译boost asio http/server 方法

    这段时间学习boost 的asio 编程,想编译asio自带的http/server的程序,无奈在网上根本找不到方法,只能自己摸索学习. 登陆boost asio 的example 目录,(我 boo ...

  10. POJ 2104 K-th Number && 洛谷 P3834 【模板】可持久化线段树 1(主席树)

    我惊奇的发现这两道题一模一样 题目背景 这是个非常经典的主席树入门题——静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个整数构成的序列,将对于指定的闭区间查询 ...