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

HINT

Source

Day2

由于是n个点n条边,所以是基环树森林,我们通过tarjan缩环后(环是捆绑选择的),就是森林

建立一个虚拟父亲后,就是一棵树了,然后就是经典的树型01背包问题了,但是zz选手竟然忘记树型背包了...

大致dp是这样的:f[i][j]表示i的子树花费j的体积产生的最大收益(如果选了i点就有值,不然就是0);

转移,对于以i为根的子树:

首先先不选i,然后和儿子的子树的收益进行合并:f[x][j]=max(f[x][j],f[x][k]+f[y][j-k]);

然后跟所有儿子搞完后,就来考虑选自身:

如果选不了自己的话,dp值为0,否则就直接加上(因为如果选不了i,那么i的子树中所有贡献都失效)

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cmath>
  4. #include<iostream>
  5. #include<cstring>
  6. #include<vector>
  7. using namespace std;
  8. typedef long long ll;
  9. const int N=100050;
  10. int gi()
  11. {
  12. int x=0,flag=1;
  13. char ch=getchar();
  14. while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}
  15. while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
  16. return x*flag;
  17. }
  18. int head[N],to[N],nxt[N],v[N],w[N],low[N],dfn[N],zhan[N],vis[N],cnt,tt,sum,tot,w2[N],v2[N],fr[N];
  19. int n,m,f[1000][1000],ru[N];
  20. vector<int>p[N];
  21. void lnk(int x,int y){
  22. to[++cnt]=y,nxt[cnt]=head[x],head[x]=cnt;
  23. }
  24. void tarjan(int x){
  25. low[x]=dfn[x]=++tt;vis[x]=1;zhan[++sum]=x;int y;
  26. for(int i=head[x];i;i=nxt[i]){
  27. y=to[i];
  28. if(!dfn[y]){
  29. tarjan(y);
  30. low[x]=min(low[y],low[x]);
  31. }
  32. else if(vis[y]) low[x]=min(low[x],dfn[y]);
  33. }
  34. if(low[x]==dfn[x]){
  35. tot++;
  36. do{
  37. y=zhan[sum--];vis[y]=0;
  38. w2[tot]+=w[y];v2[tot]+=v[y];fr[y]=tot;
  39. }while(y!=x);
  40. }
  41. }
  42. void dfs(int x){
  43. for(int i=0;i<p[x].size();i++){
  44. int y=p[x][i];dfs(y);
  45. for(int j=m-v2[x];j>=0;j--){
  46. for(int k=0;k<=j;k++)
  47. f[x][j]=max(f[x][j],f[x][k]+f[y][j-k]);
  48. }
  49. }
  50. for(int i=m;i>=0;i--){
  51. if(i>=v2[x]) f[x][i]=f[x][i-v2[x]]+w2[x];
  52. else f[x][i]=0;
  53. }
  54. }
  55. int main(){
  56. n=gi();m=gi();int x;
  57. for(int i=1;i<=n;i++) v[i]=gi();
  58. for(int i=1;i<=n;i++) w[i]=gi();
  59. for(int i=1;i<=n;i++){
  60. x=gi();if(x!=0) lnk(i,x);
  61. }
  62. for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
  63. for(int i=1;i<=n;i++)
  64. for(int j=head[i];j;j=nxt[j]){
  65. if(fr[i]!=fr[to[j]]) p[fr[to[j]]].push_back(fr[i]),ru[fr[i]]++;
  66. }
  67. int bigfa=tot+1;
  68. for(int i=1;i<=tot;i++) if(!ru[i]) p[bigfa].push_back(i);
  69. dfs(bigfa);printf("%d\n",f[bigfa][m]);
  70. }

bzoj 2427: [HAOI2010]软件安装的更多相关文章

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

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

  2. BZOJ 2427 [HAOI2010]软件安装 | 这道树形背包裸题严谨地证明了我的菜

    传送门 BZOJ 2427 题解 Tarjan把环缩成点,然后跑树形背包即可. 我用的树形背包是DFS序上搞的那种. 要注意dp数组初始化成-INF! 要注意dp顺推的时候也不要忘记看数组是否越界! ...

  3. BZOJ 2427: [HAOI2010]软件安装 tarjan + 树形背包

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

  4. BZOJ 2427: [HAOI2010]软件安装( dp )

    软件构成了一些树和一些环, 对于环我们要不不选, 要么选整个环. 跑tarjan缩点后, 新建个root, 往每个入度为0的点(强连通分量) 连边, 然后跑树dp( 01背包 ) ---------- ...

  5. bzoj 2427: [HAOI2010]软件安装【tarjan+树形dp】

    一眼最大权闭合子图,然后开始构图,画了画之后发现我其实是个智障网络流满足不了m,于是发现正确的打开方式应该是一眼树上dp 然后仔细看了看性质,发现把依赖关系建成图之后是个奇环森林,这个显然不能直接dp ...

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

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

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

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

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

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

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

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

随机推荐

  1. js-引用类型-Array

    1.数组的操作方法 <html> <meta http-equiv="content-type" charset="utf-8" /> ...

  2. 2017上半年技术文章集合【Android】—184篇文章分类汇总

    地址: http://blog.csdn.net/androidstarjack/article/details/77923753 声明 | 本文是于亚豪 原创 终端研发部 前言: 2017年已经过大 ...

  3. poj 2769 Reduced ID Numbers 同余定理

    链接:http://poj.org/problem?id=2769 题意:寻找数m,是的对于n个数的余数不同 思路:暴力,优化:同余部分不用测试 代码: #include <iostream&g ...

  4. linux安装redis(转)

    一.Redis介绍 Redis是当前比较热门的NOSQL系统之一,它是一个key-value存储系统.和Memcache类似,但很大程度补偿了Memcache的不足,它支持存储的value类型相对更多 ...

  5. THinkPHP简单漂亮的分页类 DownLoad

    PHP include_once("config.php"); require_once('page.class.php'); //分页类 $showrow = 10; //一页显 ...

  6. Hibernate学习(二)关系映射----基于外键的单向一对一

    事实上,单向1-1与N-1的实质是相同的,1-1是N-1的特例,单向1-1与N-1的映射配置也非常相似.只需要将原来的many-to-one元素增加unique="true"属性, ...

  7. 【POJ3254】Corn Fields

    http://poj.org/problem?id=3254 题意:给你一块n*m(0<n,m<=12)的地图,其中有的方格是肥沃的(用1表示),有的方格是贫瘠的(用0表示).现在约翰要在 ...

  8. Unity 5--全局光照技术

    本文整理自Unity全球官方网站,原文:UNITY 5 - LIGHTING AND RENDERING 简介全局光照,简称GI,是一个用来模拟光的互动和反弹等复杂行为的算法,要精确的仿真全局光照非常 ...

  9. JSON数据解析及gson.jar包

    从服务器端接收数据的时候,那些数据必须以浏览器能够理解的格式来发送. 服务器端的编程语言只能以如下 3 种格式返回数据: HTML XML JSON JSON一种简单的数据格式,比xml更轻巧. JS ...

  10. uva11059(最大乘积)

    Problem D - Maximum Product Time Limit: 1 second Given a sequence of integers S = {S1, S2, ..., Sn}, ...