Description

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

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

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

Input

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

Output

一个整数,代表最大价值。

Sample Input

3 10
5 5 6
2 3 4
0 1 1

Sample Output

5

Solution

首先按依赖关系建个图……然后tarjan缩个点……缩完后会是若干棵树的形态……
将若干棵树连向一个根然后DP……设f[x][i]表示在x点装了空间i的最大价值……

Code

 #include<iostream>
#include<cstring>
#include<cstdio>
#define N (1000000+1000)
using namespace std; struct Edge{int to,next;}edge[N];
int Dfn[N],Low[N],Col[N],stack[N],Ind[N],top,dfs_num,col_num;
int n,m,w[N],v[N],d[N],W[N],V[N],head[N],f[][],num_edge;
bool vis[N]; void add(int u,int v)
{
edge[++num_edge].to=v;
edge[num_edge].next=head[u];
head[u]=num_edge;
} void Tarjan(int x)
{
Dfn[x]=Low[x]=++dfs_num;
stack[++top]=x; vis[x]=true;
for (int i=head[x]; i; i=edge[i].next)
if (!Dfn[edge[i].to])
Tarjan(edge[i].to),Low[x]=min(Low[x],Low[edge[i].to]);
else if (vis[edge[i].to])
Low[x]=min(Low[x],Dfn[edge[i].to]);
if (Dfn[x]==Low[x])
{
vis[x]=false; Col[x]=++col_num;
W[col_num]=w[x]; V[col_num]=v[x];
while (stack[top]!=x)
{
vis[stack[top]]=false;
Col[stack[top]]=col_num;
W[col_num]+=w[stack[top]];
V[col_num]+=v[stack[top--]];
}
--top;
}
} void DP(int x)
{
for(int i=head[x]; i; i=edge[i].next)
{
DP(edge[i].to);
for(int j=m-W[x]; j>=; --j)
for(int k=; k<=j; ++k)
f[x][j]=max(f[x][j],f[x][k]+f[edge[i].to][j-k]);
}
for(int j=m;j>=;j--)
{
if(j>=W[x]) f[x][j]=f[x][j-W[x]]+V[x];
else f[x][j]=;
}
} int main()
{
scanf("%d%d",&n,&m);
for (int i=; i<=n; ++i) scanf("%d",&w[i]);
for (int i=; i<=n; ++i) scanf("%d",&v[i]);
for (int i=; i<=n; ++i)
{
scanf("%d",&d[i]);
if (d[i]) add(d[i],i);
}
for (int i=; i<=n; ++i)
if (!Dfn[i]) Tarjan(i); memset(head,,sizeof(head)); num_edge=;
for (int i=; i<=n; ++i)
if (d[i] && Col[i]!=Col[d[i]])
add(Col[d[i]],Col[i]),Ind[Col[i]]++;
for (int i=; i<=col_num; ++i)
if (!Ind[i]) add(col_num+,i);
DP(col_num+);
printf("%d\n",f[col_num+][m]);
}

BZOJ2427:[HAOI2010]软件安装(树形DP,强连通分量)的更多相关文章

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

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

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

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

  3. [bzoj2427][HAOI2010]软件安装——强连通分量+树形DP

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

  4. [BZOJ2427][HAOI2010]软件安装(tarjan+树形DP)

    如果依赖关系出现环,那么对于一个环里的点,要么都选要么都不选, 所以每个环可以当成一个点,也就是强连通分量 然后就可以构造出一颗树,然后树形背包瞎搞一下就行了 注意要搞一个虚拟节点当根节点 Code ...

  5. bzoj2427 [HAOI2010]软件安装——缩点+树形DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2427 今天的考试题...好不容易一次写对了树形DP,却没发现有环的情况... 发现自己 ta ...

  6. [BZOJ2427]:[HAOI2010]软件安装(塔尖+DP)

    题目传送门 题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用${W}_{i}$的磁盘空间,它的价值为${V}_{i}$.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件 ...

  7. 题解【bzoj2427 [HAOI2010]软件安装】

    Description 现在我们的手头有\(N\)个软件,对于一个软件\(i\),它要占用\(W_i\)的磁盘空间,它的价值为\(V_i\).我们希望从中选择一些软件安装到一台磁盘容量为\(M\)计算 ...

  8. bzoj2427: [HAOI2010]软件安装

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

  9. [BZOJ2427][HAOI2010]软件安装-tarjan缩点-树上dp

    <题面> 这个题真伤人 之前Tarjan和树规都没学好,吃了不少亏,仔仔细细的搞了一天,收获颇丰 先来一个Tarjan的链接:$\mathbb{O}$ 题目的数据比较友好: $dp$不对: ...

随机推荐

  1. 网易和淘宝的rem方案剖析

    以下内容到分割线前是引用前端大牛的文章,方便大家理解博主内容): 从网易与淘宝的font-size思考前端设计稿与工作流 1. 简单问题简单解决 我觉得有些web app并一定很复杂,比如拉勾网,你看 ...

  2. Firebird 有用的list函数

    语法: LIST ([ALL | DISTINCT] expression [, separator]) 示例: select list(u.code, ';') from m_user u 结果:查 ...

  3. Lakeshore用户手册

    1.场景 场景是游戏的基本组成部分,开始界面,结束界面,每个关卡都是一个场景.游戏中基于游戏的情节,可以在各个场景间跳转. 2.精灵 精灵可以理解为图片的容器.如果需要在游戏场景中插入一个静态图片,那 ...

  4. SQL中的函数以及实例

    AVG (平均) COUNT (计数) MAX (最大值) MIN (最小值) SUM (总合) 运用函数的语法是: selecte  "函数名"("列名") ...

  5. 记一次使用cmd执行java文件遇到的坑...包括“使用java命令运行class文件提示“错误:找不到或无法加载主类“的问题”

    今天写了一个java文件,类似聊天软件的东西.在eclipse里输入输出显得没感觉,于是乎就准备在cmd里输入和显示输出.如下图,我准备运行的是ChatDemo.class文件.路径是:D:\work ...

  6. Toolbar和Drawerlayout的基本使用

    参考文章: http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1118/2006.html http://www.codeceo.c ...

  7. mysql数据库详解

    001 数据库应用系统设计 1.规划   2.需求分析   3.概念模型设计   4.逻辑设计   5.物理设计   6.程序编制及调试   7.运行及维护. 002 创建数据库 CREATE DAT ...

  8. Cocos2d-js 开发记录:基本图形绘制

    做着做着想要用基本绘图函数画个矩形,在cocos2d-js 3.0里可以使用DrawNode var dn = new cc.DrawNode(); var ltp = cc.p(0, 32); va ...

  9. 从Pc转向H5开发遇到的适配问题思考

    1.首先说滚动条 移动端开发在不设置任何适配和viewport宽度的情况下,以iphone5为例:屏幕界面的逻辑分辨率是320x568,在谷歌浏览器的界面下屏幕的可视宽度是980px(谷歌设置的,每个 ...

  10. 廖雪峰JavaScript练习题

    练习:不要使用JavaScript内置的parseInt()函 数,利用map和reduce操作实现一个string2int()函数: <!DOCTYPE html> <html&g ...