[HAOI2010]软件安装(树形背包,tarjan缩点)
题目描述
现在我们的手头有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 )
输出格式:
一个整数,代表最大价值
思路:
望过去满眼的树形DP
和前面写的选课一模一样,只是cost需要输入
但很显然,你会这样

为什么呢?
后来想了半天,才发现
如果1依赖于2,2依赖于2,3依赖于1的化,这几个个点其实也能选,不过要选得一起选
所以,我们要用tarjan来缩点
把所有满足上图关系的点变为一个新点,并且与0连边即可
Q:环套树怎么办?
因为一个点只唯一依赖另一个点,所以入边一定为1
所以一定是环到树,不可能树到环,所以缩点没问题
懒了一下,用了stl
代码:
// luogu-judger-enable-o2
#include<iostream>
#include<stack>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#define rii register int i
#define rij register int j
#define rik register int k
using namespace std;
const int N=;const int M=;
struct E{
int to,nxt;
}ed[N<<];
int H[N<<],cnt;
stack<int>sta;
bool ins[N];
int dp[N][M],v[N],w[N],d[N];
int tot,dfn[N],low[N];
int num,col[N],fv[N],fw[N];
int n,m,rd[N];
void add(int x,int y)
{
cnt++;
ed[cnt].to=y;
ed[cnt].nxt=H[x];
H[x]=cnt;
return;
}
void read(int &in)
{
int x=,f=;
char ch;
for(ch=getchar();(ch<''||ch>'')&&ch!='-';ch=getchar());
if(ch=='-')
{
f=-;
ch=getchar();
}
while(ch>=''&&ch<='')
{
x=(x<<)+(x<<)+ch-'';
ch=getchar();
}
in=x*f;
return;
}
void tarjan(int x)
{
dfn[x]=low[x]=++tot;
ins[x]=true;sta.push(x);
int t,k;
for(rii=H[x];i;i=ed[i].nxt)
{
t=ed[i].to;
if(!dfn[t])
{
tarjan(t);
low[x]=min(low[x],low[t]);
}
else if(ins[t])
{
low[x]=min(low[x],dfn[t]);
}
}
if(low[x]==dfn[x])
{
num++;
do
{
k=sta.top();
sta.pop();
col[k]=num;
fw[num]+=w[k];
fv[num]+=v[k];
ins[k]=false;
}
while(k!=x);
}
return;
}
void dfs(int x)
{
for(rii=fw[x];i<=m;i++)
{
dp[x][i]=fv[x];
}
int t;
for(rii=H[x];i;i=ed[i].nxt)
{
t=ed[i].to;
dfs(t);
for(rij=m-fw[x];j>=;j--)
{
for(rik=;k<=j;k++)
{
dp[x][j+fw[x]]=max(dp[x][j+fw[x]],dp[x][j+fw[x]-k]+dp[t][k]);
}
}
}
return;
}
int main()
{
// freopen("software.in","r",stdin);
// freopen("software.out","w",stdout);
read(n);
read(m);
for(rii=;i<=n;i++)
{
read(w[i]);
}
for(rii=;i<=n;i++)
{
read(v[i]);
}
for(rii=;i<=n;i++)
{
read(d[i]);
if(d[i])
{
add(d[i],i);
}
}
for(rii=;i<=n;i++)
{
if(!dfn[i])
{
tarjan(i);
}
}
memset(H,,sizeof(H));
cnt=;
for(rii=;i<=n;i++)
{
if(col[i]!=col[d[i]]&&d[i])
{
add(col[d[i]],col[i]);
rd[col[i]]++;
}
}
for(rii=;i<=num;i++)
{
if(!rd[i])
{
add(num+,i);
}
dfs(num+);
}
printf("%d\n",dp[num+][m]);
return ;
}
// luogu-judger-enable-o2
#include<iostream>
#include<stack>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#define rii register int i
#define rij register int j
#define rik register int k
using namespace std;
const int N=;const int M=;
struct E{
int to,nxt;
}ed[N<<];
int H[N<<],cnt;
stack<int>sta;
bool ins[N];
int dp[N][M],v[N],w[N],d[N];
int tot,dfn[N],low[N];
int num,col[N],fv[N],fw[N];
int n,m,rd[N];
void add(int x,int y)
{
cnt++;
ed[cnt].to=y;
ed[cnt].nxt=H[x];
H[x]=cnt;
return;
}
void read(int &in)
{
int x=,f=;
char ch;
for(ch=getchar();(ch<''||ch>'')&&ch!='-';ch=getchar());
if(ch=='-')
{
f=-;
ch=getchar();
}
while(ch>=''&&ch<='')
{
x=(x<<)+(x<<)+ch-'';
ch=getchar();
}
in=x*f;
return;
}
void tarjan(int x)
{
dfn[x]=low[x]=++tot;
ins[x]=true;sta.push(x);
int t,k;
for(rii=H[x];i;i=ed[i].nxt)
{
t=ed[i].to;
if(!dfn[t])
{
tarjan(t);
low[x]=min(low[x],low[t]);
}
else if(ins[t])
{
low[x]=min(low[x],dfn[t]);
}
}
if(low[x]==dfn[x])
{
num++;
do
{
k=sta.top();
sta.pop();
col[k]=num;
fw[num]+=w[k];
fv[num]+=v[k];
ins[k]=false;
}
while(k!=x);
}
return;
}
void dfs(int x)
{
for(rii=fw[x];i<=m;i++)
{
dp[x][i]=fv[x];
}
int t;
for(rii=H[x];i;i=ed[i].nxt)
{
t=ed[i].to;
dfs(t);
for(rij=m-fw[x];j>=;j--)
{
for(rik=;k<=j;k++)
{
dp[x][j+fw[x]]=max(dp[x][j+fw[x]],dp[x][j+fw[x]-k]+dp[t][k]);
}
}
}
return;
}
int main()
{
// freopen("software.in","r",stdin);
// freopen("software.out","w",stdout);
read(n);
read(m);
for(rii=;i<=n;i++)
{
read(w[i]);
}
for(rii=;i<=n;i++)
{
read(v[i]);
}
for(rii=;i<=n;i++)
{
read(d[i]);
if(d[i])
{
add(d[i],i);
}
}
for(rii=;i<=n;i++)
{
if(!dfn[i])
{
tarjan(i);
}
}
memset(H,,sizeof(H));
cnt=;
for(rii=;i<=n;i++)
{
if(col[i]!=col[d[i]]&&d[i])
{
add(col[d[i]],col[i]);
rd[col[i]]++;
}
}
for(rii=;i<=num;i++)
{
if(!rd[i])
{
add(num+,i);
}
dfs(num+);
}
printf("%d\n",dp[num+][m]);
return ;
[HAOI2010]软件安装(树形背包,tarjan缩点)的更多相关文章
- BZOJ2427:[HAOI2010]软件安装(树形DP,强连通分量)
Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和 ...
- HAOI2010软件安装(树形背包)
HAOI2010软件安装(树形背包) 题意 有n个物品,每个物品最多会依赖一个物品,但一个物品可以依赖于一个不独立(依赖于其它物品)的物品,且可能有多个物品依赖一个物品,并且依赖关系可能形成一个环.现 ...
- 【BZOJ2427】[HAOI2010]软件安装 Tarjan+树形背包
[BZOJ2427][HAOI2010]软件安装 Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为 ...
- bzoj 2427 [HAOI2010]软件安装 Tarjan缩点+树形dp
[HAOI2010]软件安装 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2029 Solved: 811[Submit][Status][Dis ...
- Tarjan+树形DP【洛谷P2515】[HAOI2010]软件安装
[洛谷P2515][HAOI2010]软件安装 题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得 ...
- [HAOI2010]软件安装(Tarjan,树形dp)
[HAOI2010]软件安装 题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可 ...
- BZOJ_2427_[HAOI2010]软件安装_tarjan+树形DP
BZOJ_2427_[HAOI2010]软件安装_tarjan+树形DP 题意: 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁 ...
- [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 ...
- 【BZOJ2427】[HAOI2010]软件安装(动态规划,Tarjan)
[BZOJ2427][HAOI2010]软件安装(动态规划,Tarjan) 题面 BZOJ 洛谷 题解 看到这类题目就应该要意识到依赖关系显然是可以成环的. 注意到这样一个性质,依赖关系最多只有一个, ...
随机推荐
- 自己用到的vim常用命令
一.前言 这里整理的是我在实习期间用到的常用vim命令,特记录如下,以免忘记. 二.vim常用命令 1.vim中的光标移动 shift+6(^):跳到行首(第一个非空格字符)(注:在shell跳到行首 ...
- 位运算(6)——Number Complement
Given a positive integer, output its complement number. The complement strategy is to flip the bits ...
- 网易回合制游戏录像批量下载(失效 不是因为代码 是因为网易官方关闭了录像网站 :P)
最近在访问网易大话西游2的录像专区时,发现页面还是很早之前的板式,网易的编辑并没有打算重新美化的打算,不由得内心一寒,结合之前好几个回合制游戏的倒闭,让很多人回顾都没办法回顾, 而且,很多人现在也没有 ...
- 针对 IE的 的优化
针对 IE 的优化 有些时候,你需要对 IE 浏览器的 bug 定义一些特别的规则,这里有太多的 CSS 技巧(hacks),我只使用其中的两种方法,不 管微软在即将发布的 IE7 beta 版里是否 ...
- 【Linux】Linux远程登陆
登录任务 Windows主机--远程登录--Linux主机 一.登陆前提准备 1.1 确保网络通畅 确保从Windows 能够Ping通Linux 1.2 关闭Linux防火墙 //前提:以root管 ...
- 关于Android中的ViewTreeObserver
ViewTreeObserver结构 extends Object java.lang.Object ↳ android.view.ViewTreeObserver ViewTreeObserver概 ...
- Socket.Receive 无法预知字节长度的数据接收
话不多说直接上代码: string recvStr = ""; byte[] recvBytes = new byte[1024]; int bytes; do { bytes = ...
- Laravel SMS 短信发送包
Laravel Sms Laravel 贴合实际需求同时满足多种通道的短信发送组件 我们基于业务需求在 overtrue/easy-sms 基础进行扩展开发,主要实现如下目标: 支持短信验证码直接在 ...
- 再学UML-深入浅出UML类图(三)
类与类之间的关系(2) 2. 依赖关系 依赖(Dependency)关系是一种使用关系,特定事物的改变有可能会影响到使用该事物的其他事物,在需要表示一个事物使用另一个事物时使用依赖关系. ...
- Perl实用中文处理步骤(修改版)
发信人: FenRagwort (泽), 信区: Perl标 题: Perl实用中文处理步骤(修改版)发信站: 水木社区 (Mon Feb 14 12:52:14 2011), 转信 (修改版 感谢 ...