题目描述

现在我们的手头有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

代码:

  1. // luogu-judger-enable-o2
  2. #include<iostream>
  3. #include<stack>
  4. #include<cstdio>
  5. #include<cstring>
  6. #include<cstdlib>
  7. #define rii register int i
  8. #define rij register int j
  9. #define rik register int k
  10. using namespace std;
  11. const int N=;const int M=;
  12. struct E{
  13. int to,nxt;
  14. }ed[N<<];
  15. int H[N<<],cnt;
  16. stack<int>sta;
  17. bool ins[N];
  18. int dp[N][M],v[N],w[N],d[N];
  19. int tot,dfn[N],low[N];
  20. int num,col[N],fv[N],fw[N];
  21. int n,m,rd[N];
  22. void add(int x,int y)
  23. {
  24. cnt++;
  25. ed[cnt].to=y;
  26. ed[cnt].nxt=H[x];
  27. H[x]=cnt;
  28. return;
  29. }
  30. void read(int &in)
  31. {
  32. int x=,f=;
  33. char ch;
  34. for(ch=getchar();(ch<''||ch>'')&&ch!='-';ch=getchar());
  35. if(ch=='-')
  36. {
  37. f=-;
  38. ch=getchar();
  39. }
  40. while(ch>=''&&ch<='')
  41. {
  42. x=(x<<)+(x<<)+ch-'';
  43. ch=getchar();
  44. }
  45. in=x*f;
  46. return;
  47. }
  48. void tarjan(int x)
  49. {
  50. dfn[x]=low[x]=++tot;
  51. ins[x]=true;sta.push(x);
  52. int t,k;
  53. for(rii=H[x];i;i=ed[i].nxt)
  54. {
  55. t=ed[i].to;
  56. if(!dfn[t])
  57. {
  58. tarjan(t);
  59. low[x]=min(low[x],low[t]);
  60. }
  61. else if(ins[t])
  62. {
  63. low[x]=min(low[x],dfn[t]);
  64. }
  65. }
  66. if(low[x]==dfn[x])
  67. {
  68. num++;
  69. do
  70. {
  71. k=sta.top();
  72. sta.pop();
  73. col[k]=num;
  74. fw[num]+=w[k];
  75. fv[num]+=v[k];
  76. ins[k]=false;
  77. }
  78. while(k!=x);
  79. }
  80. return;
  81. }
  82. void dfs(int x)
  83. {
  84. for(rii=fw[x];i<=m;i++)
  85. {
  86. dp[x][i]=fv[x];
  87. }
  88. int t;
  89. for(rii=H[x];i;i=ed[i].nxt)
  90. {
  91. t=ed[i].to;
  92. dfs(t);
  93. for(rij=m-fw[x];j>=;j--)
  94. {
  95. for(rik=;k<=j;k++)
  96. {
  97. dp[x][j+fw[x]]=max(dp[x][j+fw[x]],dp[x][j+fw[x]-k]+dp[t][k]);
  98. }
  99. }
  100. }
  101. return;
  102. }
  103. int main()
  104. {
  105. // freopen("software.in","r",stdin);
  106. // freopen("software.out","w",stdout);
  107. read(n);
  108. read(m);
  109. for(rii=;i<=n;i++)
  110. {
  111. read(w[i]);
  112. }
  113. for(rii=;i<=n;i++)
  114. {
  115. read(v[i]);
  116. }
  117. for(rii=;i<=n;i++)
  118. {
  119. read(d[i]);
  120. if(d[i])
  121. {
  122. add(d[i],i);
  123. }
  124. }
  125. for(rii=;i<=n;i++)
  126. {
  127. if(!dfn[i])
  128. {
  129. tarjan(i);
  130. }
  131. }
  132. memset(H,,sizeof(H));
  133. cnt=;
  134. for(rii=;i<=n;i++)
  135. {
  136. if(col[i]!=col[d[i]]&&d[i])
  137. {
  138. add(col[d[i]],col[i]);
  139. rd[col[i]]++;
  140. }
  141. }
  142. for(rii=;i<=num;i++)
  143. {
  144. if(!rd[i])
  145. {
  146. add(num+,i);
  147. }
  148. dfs(num+);
  149. }
  150. printf("%d\n",dp[num+][m]);
  151. return ;
  152. }
  1. // luogu-judger-enable-o2
  2. #include<iostream>
  3. #include<stack>
  4. #include<cstdio>
  5. #include<cstring>
  6. #include<cstdlib>
  7. #define rii register int i
  8. #define rij register int j
  9. #define rik register int k
  10. using namespace std;
  11. const int N=;const int M=;
  12. struct E{
  13. int to,nxt;
  14. }ed[N<<];
  15. int H[N<<],cnt;
  16. stack<int>sta;
  17. bool ins[N];
  18. int dp[N][M],v[N],w[N],d[N];
  19. int tot,dfn[N],low[N];
  20. int num,col[N],fv[N],fw[N];
  21. int n,m,rd[N];
  22. void add(int x,int y)
  23. {
  24. cnt++;
  25. ed[cnt].to=y;
  26. ed[cnt].nxt=H[x];
  27. H[x]=cnt;
  28. return;
  29. }
  30. void read(int &in)
  31. {
  32. int x=,f=;
  33. char ch;
  34. for(ch=getchar();(ch<''||ch>'')&&ch!='-';ch=getchar());
  35. if(ch=='-')
  36. {
  37. f=-;
  38. ch=getchar();
  39. }
  40. while(ch>=''&&ch<='')
  41. {
  42. x=(x<<)+(x<<)+ch-'';
  43. ch=getchar();
  44. }
  45. in=x*f;
  46. return;
  47. }
  48. void tarjan(int x)
  49. {
  50. dfn[x]=low[x]=++tot;
  51. ins[x]=true;sta.push(x);
  52. int t,k;
  53. for(rii=H[x];i;i=ed[i].nxt)
  54. {
  55. t=ed[i].to;
  56. if(!dfn[t])
  57. {
  58. tarjan(t);
  59. low[x]=min(low[x],low[t]);
  60. }
  61. else if(ins[t])
  62. {
  63. low[x]=min(low[x],dfn[t]);
  64. }
  65. }
  66. if(low[x]==dfn[x])
  67. {
  68. num++;
  69. do
  70. {
  71. k=sta.top();
  72. sta.pop();
  73. col[k]=num;
  74. fw[num]+=w[k];
  75. fv[num]+=v[k];
  76. ins[k]=false;
  77. }
  78. while(k!=x);
  79. }
  80. return;
  81. }
  82. void dfs(int x)
  83. {
  84. for(rii=fw[x];i<=m;i++)
  85. {
  86. dp[x][i]=fv[x];
  87. }
  88. int t;
  89. for(rii=H[x];i;i=ed[i].nxt)
  90. {
  91. t=ed[i].to;
  92. dfs(t);
  93. for(rij=m-fw[x];j>=;j--)
  94. {
  95. for(rik=;k<=j;k++)
  96. {
  97. dp[x][j+fw[x]]=max(dp[x][j+fw[x]],dp[x][j+fw[x]-k]+dp[t][k]);
  98. }
  99. }
  100. }
  101. return;
  102. }
  103. int main()
  104. {
  105. // freopen("software.in","r",stdin);
  106. // freopen("software.out","w",stdout);
  107. read(n);
  108. read(m);
  109. for(rii=;i<=n;i++)
  110. {
  111. read(w[i]);
  112. }
  113. for(rii=;i<=n;i++)
  114. {
  115. read(v[i]);
  116. }
  117. for(rii=;i<=n;i++)
  118. {
  119. read(d[i]);
  120. if(d[i])
  121. {
  122. add(d[i],i);
  123. }
  124. }
  125. for(rii=;i<=n;i++)
  126. {
  127. if(!dfn[i])
  128. {
  129. tarjan(i);
  130. }
  131. }
  132. memset(H,,sizeof(H));
  133. cnt=;
  134. for(rii=;i<=n;i++)
  135. {
  136. if(col[i]!=col[d[i]]&&d[i])
  137. {
  138. add(col[d[i]],col[i]);
  139. rd[col[i]]++;
  140. }
  141. }
  142. for(rii=;i<=num;i++)
  143. {
  144. if(!rd[i])
  145. {
  146. add(num+,i);
  147. }
  148. dfs(num+);
  149. }
  150. printf("%d\n",dp[num+][m]);
  151. 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. 重构指南 - 封装集合(Encapsulate Collection)

    封装就是将相关的方法或者属性抽象成为一个对象. 封装的意义: 对外隐藏内部实现,接口不变,内部实现自由修改. 只返回需要的数据和方法. 提供一种方式防止数据被修改. 更好的代码复用. 当一个类的属性类 ...

  2. PAT 1042 Shuffling Machine

    #include <cstdio> #include <cstdlib> #include <vector> using namespace std; ] = {' ...

  3. 1729 单词查找树 2000年NOI全国竞赛

    1729 单词查找树 2000年NOI全国竞赛 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 大师 Master         题目描述 Description 在进行文法分析的 ...

  4. hook_myhook.api.php文件什么用

    看源文件的时候发现有个user.api.php文件,里面定义了一个新的钩子,$hook_user_categories,但是,drupal核心里面没有,我推测是自定义 的钩子函数,然后在*.modul ...

  5. alpinelinux

    https://wiki.alpinelinux.org/wiki/Tutorials_and_Howtos https://nixos.org/nix/manual/#ch-installing-b ...

  6. ArcGIS Enterprise 10.5.1 静默安装部署记录(Centos 7.2 minimal)- 6、总结

    安装小结 安装完成后,首先我们需要将Datastore托管给Server,再将Server托管给Portal以此来完成整个单机版Enterprise 部署流程.为了测试流程是否正确,我们可以采用上传一 ...

  7. jquery简介(一)

    摘要:简要介绍jquery的起源,以及为什么需要使用jquery. jquery的优点 jquery体量小,加载速度快,其本身具有的功能使JavaScript应用程序开发人员的工作变得分外轻松.其中最 ...

  8. matlab练习程序(弧形、圆柱投影的复原)

    前一段介绍了从矩形图像到圆柱的正向投影,看这里和这里.今天介绍如何从已经投影的图像反映射到原图像上. 本来此种变换一定是需要数学公式的,不过这里只是用了一个很简单的方式来完成反映射. 具体就把每一列有 ...

  9. 一个简单的 HTML 文档,带有最基本的必需的元素

    <html> <head> <title>文档的标题</title> </head> <body> 文档的内容... ... & ...

  10. BIEE入门(二)物理层的定义

    使用BIEE的第一步是使用admintool去建立一个多维数据模型,而建立多维数据模型的第一步则是建立物理层,请注意因为BIEE本身并不存 储数据,所以所谓BIEE物理层的意义是需要在BIEE里建立各 ...