题目描述

现在我们的手头有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. [Linq To Sql]解决join时的Collation冲突

    背景 现在两表 A:

  2. python学习(七)--豆瓣爬取电影名,评分以及演员

    import requestsimport re #爬取豆瓣电影排名pageNum = int(input("要查看第几页电影分数:"))#已知豆瓣默认每页展示20条#url= & ...

  3. TortoiseSVN安装

    安装说明 开发人员强烈建议使用IDE中的SVN插件更加智能与人性化. 首先安装SVN客户端,windows一般选择乌龟客户端https://tortoisesvn.net/downloads.html ...

  4. python之高阶函数map/reduce

    L = [] for n in [1, 2, 3, 4, 5, 6, 7, 8, 9]: L.append(f(n)) print(L) Python内建了map()和reduce()函数. 我们先看 ...

  5. 五校联考模拟赛Day2T2矩阵(容斥原理)

    题意 $n * m$的网格,对其进行黑白染色,问每一行每一列至少有一个黑格子的方案数. Sol 考场上只会$n^3$的dp,还和指数级枚举一个分qwq 设$f[i][j]$表示到了第$i$行,已经有$ ...

  6. ref 和 out 的区别

    ref和out都是C#中的关键字,所实现的功能也差不多,都是指定一个参数按照引用传递. 对于编译后的程序而言,它们之间没有任何区别,也就是说它们只有语法区别. 总结起来,他们有如下语法区别: 1.re ...

  7. 03_CronTrigger

    [Cron表达式] Quartz使用类似于Linux下的Cron表达式定义的时间规则,Cron表达式由6到7个空格分隔的时间字段组成. [ 字符说明 ] * :可以用在所有字段中,表示对应时间域内的每 ...

  8. mybatis3 step by step 快速上手

    作者:Panda Fang 出处:http://www.cnblogs.com/lonkiss/p/6895617.html 原创文章,转载请注明作者和出处,未经允许不可用于商业营利活动 官方网站 h ...

  9. Tomcat 数据源的原理、配置、使用

    1.数据源的作用及操作原理 在程序代码中使用数据源是可以提升操作性能的,这种性能的提升依靠于运行的原理. 传统JDBC操作步骤 1.加载数据库驱动程序,数据库驱动程序通过CLASSPATH配置: 2. ...

  10. WAKE-WIN10-SOFT-软件-Matlab配置及工具箱

    1Matlab 1,1Matlab下载,安装,配置,,, 1,2 2工具箱 2,1LibSVM 必应:https://www.bing.com/search?q=libsvm&qs=n& ...