题目描述

现在我们的手头有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. FTP FileZilla Server 本地加密C# 实现

    最近公司要做一个资料管理模块,因系统是C/S架构,原来小文件都是直接使用7Z压缩后保存到SQL Server数据库 而资料管理模块也就是文件上传,下载加权限管理,考虑文件较多,还可能比较大,所以打算在 ...

  2. vue 音乐播放器报错

    使用Vue报错[Vue warn]: Error in nextTick: "TypeError: fn.bind is not a function"页面进不去. 检查:看看da ...

  3. Android 马甲包制作流程

    一.马甲包的制作流程 1.配置马甲包的applicationId以及应用名称 在app的build.gradle文件中添加马甲包的配置 android { signingConfigs { confi ...

  4. linux下的动态链接库管理

    LD_LIBRARY_PATH Linux环境变量名,该环境变量主要用于指定查找共享库(动态链接库)时除了默认路径之外的其他路径.(该路径在默认路径之前查找) 移植程序时的经常碰到需要使用一些特定的动 ...

  5. 如何将bug杀死在摇篮里?

    阿里妹导读:在欧洲中世纪的传说中,有一种叫“人狼”的妖怪,就是人面狼身.它们会讲人话,专在月圆之夜去袭击人类.而且传说中对“人狼”用一般的枪弹是不起作用的,普通子弹都伤不到也打不死它,只有一种用银子作 ...

  6. geth访问公有链

    同步以太坊,配置rpc地址 mkdir /opt/blockchain nohup geth --syncmode "fast" --cache=1024 --maxpeers 3 ...

  7. 关于使用metronic时里modal模拟框使用ueditor时不能全屏的情况

    ueditor里有这么断代码, 1.初始显示状态下(非全屏),修改一下代码的z-index UE.Editor.defaultOptions = function(editor){ var _url ...

  8. TinkPHP去重统计查询

    当统计一个有重复的字段可以用这个方法 $count = $model->where($map)->count('distinct(id)'); 转自 http://www.thinkphp ...

  9. static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

    查看HashMap源码,发现这个static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;  值为16. 这个是位移算法. 例如: 4<& ...

  10. 什么是SWP文件?能否删除swp文件?

    SWP意思就是交换文件..SWP是各种操作系统(Windows或Linux)使用的交换文件的文件扩展名. 可以安全地清理SWP文件以释放磁盘空间. 要清理SWP文件,请按照以下步骤操作: 运行WinU ...