题目:

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

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

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

(0≤N≤100,0≤M≤500,0≤Wi​≤M,0≤Vi≤1000)

大意:

有向图 选一个节点同时需要选它的前驱,求满足容量关系的最大点权和

思路:

首先依赖关系可以成环 故选了其中一个相当于选了所有 故可以缩点处理

缩完点后 由于一个点只有一个前驱 故剩下的图构成森林 将其与0号点相连构成一个树 此时本题就成了树上背包的裸题 题干疯狂暗示 注意选了父亲才能选儿子故此时状态dp[u][w]是选了u节点后该子树在w容量时取得的最优解 又由于选了u节点故dp[u][w]需要初始化 由状态定义知最终答案在dp[0][M]取得

下面是代码

 #include <cstdio>
#include <iostream>
#define r(x) x=read()
#define MAXX 1005
using namespace std;
int f[MAXX][MAXX],w2[MAXX],z2[MAXX],w[MAXX],z[MAXX],sta[MAXX],id[MAXX],
low[MAXX],dfn[MAXX],h[][MAXX],cnt[],fa[MAXX],k,num,top,n,m,ans,to;
struct edge{int to,nex;}e[][];
void add(int u,int to,int d)
{
cnt[d]++;
e[d][cnt[d]]=(edge){to,h[d][u]};
h[d][u]=cnt[d];
}
void tarjan(int u)
{
low[u]=dfn[u]=++k;sta[++top]=u;
for(int i=h[][u];i;i=e[][i].nex)
{
int to=e[][i].to;
if(!dfn[to])
tarjan(to),low[u]=min(low[u],low[to]);
else
if(!id[to])
low[u]=min(low[u],dfn[to]);
}
if(low[u]==dfn[u])
{
id[u]=++num;
while(sta[top]!=u)
{
id[sta[top]]=num;
--top;
}
--top;
}
}
void dfs(int u)
{
for(int i=w[u];i<=m;++i) f[u][i]=z[u];
for(int p=h[][u];p;p=e[][p].nex)
{
dfs(e[][p].to);
for(int i=m;i>=w[u];--i)
for(int j=;j<=i-w[u];++j)
f[u][i]=max(f[u][i],f[u][i-j]+f[e[][p].to][j]);
}
}
int read()
{
char ch=;int w=;
while(ch<''||ch>''){ch=getchar();}
while(ch>=''&&ch<=''){w=w*+ch-'';ch=getchar();}
return w;
}
int main()
{
r(n),r(m);
for(int i=;i<=n;++i)
r(w2[i]);
for(int i=;i<=n;++i)
r(z2[i]);
for(int i=;i<=n;++i)
{
r(to);
if(to)
add(to,i,);
}
for(int i=;i<=n;++i)
if(!id[i])
tarjan(i);
for(int i=;i<=n;++i)
{
w[id[i]]+=w2[i];
z[id[i]]+=z2[i];
for(int j=h[][i];j;j=e[][j].nex)
{
if(id[e[][j].to]!=id[i])
add(id[i],id[e[][j].to],),++fa[id[e[][j].to]];
}
}
for(int i=;i<=num;++i)
if(!fa[i]) add(,i,);
dfs();
printf("%d",f[][m]);
return ;
}

最新文章

  1. 移动web资源整理
  2. 数字与字母 随机数小demo
  3. IIS32位,64位模式下切换
  4. Linqer工具
  5. delphi xe5 android 开发数据访问server端(二)
  6. [Design Pattern] Factory Pattern 简单案例
  7. JProtector java应用加密工具
  8. ActiveMQ in Action(2) - Transport
  9. Android基础工具函数代码集
  10. 安卓高级4 第三方库SlidingMenu的使用
  11. Spring+Quartz集群环境下定时调度的解决方案
  12. leetcode — minimum-window-substring
  13. 重装系统之 Win10 镜像安装
  14. [转]原生JS-查找相邻的元素-siblings方法的实现
  15. ElasticSearch(四):使用Java连接ElasticSearch集群
  16. [bash] 几个以前没注意过的小知识
  17. Viewing the interface of your Swift code,查看Swift代码的头文件的三种方法
  18. Stylus的使用
  19. reids非关系性数据库
  20. ng的概念层次(官方文档摘录)

热门文章

  1. UNIX标准C - 进程之间的通信
  2. 在最新的 create-react-app 中添加 less 支持
  3. [CSP-S模拟测试]:666(模拟)
  4. EM 算法资料
  5. ACM ICPC 2011-2012 Northeastern European Regional Contest(NEERC)K Kingdom Roadmap
  6. a = a + b 与 a += b 的区别
  7. MySQL Online DDL工具
  8. 卡方检验(python代码实现)
  9. linux fedora原生的快捷键操作
  10. Delphi下利用WinIo模拟鼠标键盘详解 有参考价值