题目描述

现在我们的手头有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缩点)的更多相关文章

  1. BZOJ2427:[HAOI2010]软件安装(树形DP,强连通分量)

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

  2. HAOI2010软件安装(树形背包)

    HAOI2010软件安装(树形背包) 题意 有n个物品,每个物品最多会依赖一个物品,但一个物品可以依赖于一个不独立(依赖于其它物品)的物品,且可能有多个物品依赖一个物品,并且依赖关系可能形成一个环.现 ...

  3. 【BZOJ2427】[HAOI2010]软件安装 Tarjan+树形背包

    [BZOJ2427][HAOI2010]软件安装 Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为 ...

  4. bzoj 2427 [HAOI2010]软件安装 Tarjan缩点+树形dp

    [HAOI2010]软件安装 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2029  Solved: 811[Submit][Status][Dis ...

  5. Tarjan+树形DP【洛谷P2515】[HAOI2010]软件安装

    [洛谷P2515][HAOI2010]软件安装 题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得 ...

  6. [HAOI2010]软件安装(Tarjan,树形dp)

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

  7. BZOJ_2427_[HAOI2010]软件安装_tarjan+树形DP

    BZOJ_2427_[HAOI2010]软件安装_tarjan+树形DP 题意: 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁 ...

  8. [BZOJ2427][HAOI2010]软件安装(Tarjan+DP)

    2427: [HAOI2010]软件安装 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1987  Solved: 791[Submit][Statu ...

  9. bzoj2427:[HAOI2010]软件安装(Tarjan+tree_dp)

    2427: [HAOI2010]软件安装 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1053  Solved: 424[Submit][Statu ...

  10. 【BZOJ2427】[HAOI2010]软件安装(动态规划,Tarjan)

    [BZOJ2427][HAOI2010]软件安装(动态规划,Tarjan) 题面 BZOJ 洛谷 题解 看到这类题目就应该要意识到依赖关系显然是可以成环的. 注意到这样一个性质,依赖关系最多只有一个, ...

随机推荐

  1. SQLAlchemy的使用---数据库的创建与连接

    # 1. 导入SQLAlchemy from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Col ...

  2. Arcgis flex 切片地图麻点

    在arcgis server中发布地图切片完成后,有时候在访问地图的时候会出现很多麻点, 其实是你切片的时候没有注意到一些选项.... 默认的切片是PNG8,说到这可能就明白了吧,png8的色彩范围: ...

  3. GIS中的坐标系定义与转换

    GIS中的坐标系定义与转换 青岛海洋地质研究所 戴勤奋 2002-3-27 14:22:47 ----------------------------------------------------- ...

  4. android launcher

    1.android_launcher的源码详细分析 2.android---launcher 3.Android 4.4 Launcher3桌面源码分析 4.通过深度剖析Android之Launche ...

  5. mybooklist 日志5.12

    这是一个很悲伤的日子. 今天,我不发朋友圈了.可手头的工作还是要做的,虽然说这是工作,也不能完全算. 在上班的时间做的事情,可以称得上工作,可这不是老板交给我做的事情.国有企业领导很两难,老板你是要辞 ...

  6. Hadoop ->> MapReduce编程模型

    对于MapReduce模型的实现,有Java等一些语言实现了接口,或者用像Hive/Pig这样的平台来操作.MapReduce由Map函数.Reduce函数和Main函数实现.第一步,源数据文件按默认 ...

  7. MonkeyRunner之MonkeyRecorder录制回放脚本

    MonkeyRunner强大的功能之一便是允许用户自由录制需要的脚本,录制和回放需要两个脚本文件 monkey_recorder.py和monkey_playback.py 首先来看 monkey_r ...

  8. CSS3中REM使用详解

    px 在Web页面制作中,我们一般使用“px”来设置我们的文本,因为他比较稳定和精确.但是这种方法存在一个问题,当用户在浏览器中浏览我们制作的Web页面时,他改变了浏览器的字体大小(虽然一般人不会去改 ...

  9. March 1 2017 Week 9 Wednesday

    If you are serious giving up something, giving up is not serious at all. 如果你慎重地决定要放弃,那么放弃本身就没什么大不了的. ...

  10. oozie coordinator 定时调度

      (本段内容摘自http://blog.sina.com.cn/s/blog_e699b42b0102xjqw.html  Oozie总结 行成于思的博客)      Oozie提出了Coordin ...