当前位置: 首页 > news >正文

题解:软件安装

题目:

https://www.luogu.com.cn/problem/P2515

注意软件的依赖关系可能形成一个环,a依赖b,b依赖c,c依赖a,如果想要让环上的一个软件起作用必须得下载环上的所有软件。所以需要先缩点。

缩点完成后重新建图,该题就是经典的树形依赖背包问题。

定义dp[i][j]为以i为根的子树,在选择了i的前提下背包容量为j时的最大价值。
dp过程中,外层循环枚举背包容量,内层循环枚举分配给当前子树的背包容量,然后对于父节点u当前背包容量为j和子节点v以及分配给子树的背包容量为k,那么dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]),父节点和遍历到v之前的其他子树用j-k容量的最大价值加上子树v用k容量产生的最大价值。因为要提前知道子节点的情况,所以进行递归,从下往上更新。

考虑到可能会有多棵树,所以创建一个虚拟节点0连接每棵树的根节点。那么dp完后的答案就是dp[0][m]

dp部分:

voiddfs(intu){if(cost[u]>m)//父节点的容量已经超过整个背包容量,直接放弃这棵子树return;dp[u][cost[u]]=val[u];//先选择父节点(这棵子树的根节点)for(intv:ad[u]){dfs(v);//递归收集子树的情况for(intj=m;j>=cost[u];j--)//倒着枚举背包容量,保证只选择该子树一次{for(inti=0;i<=j-cost[u];i++)//枚举可以分配给这棵子树的容量{dp[u][j]=max(dp[u][j],dp[u][j-i]+dp[v][i]);}}}}

软件多次安装价值不会叠加,所以是01背包问题。外层循环需要倒着枚举,因为dp[u][j]的更新需要依赖dp表同层且列数更小的dp[u][j-i],需要保证dp[u]这一层j列前的数据是上一次产生的数据。如果正着遍历的话,dp[u][j-i]可能已经被j-i列前面以及子树v的数据更新过,这代表已经选择了子树v一次,如果用这个数据去更新dp[u][j]的话,会导致v又被选择一次。

可能出现的情况:

正着遍历是先1后2,j-i位置已经算入了子树v的价值,到位置j时,依赖j-i位置和子树v进行更新,v会再次被算入。总之正序遍历会导致v的贡献被累加多次,需要保证j前面的数据还没有被更新过,所以需要倒着进行更新。

总代码:

//缩点建图统计入边复杂度为O(n),去重为O(nlogn),每条树边进行一次dp,dp过程为O(n*m^2)//前两项过小忽略,整体复杂度为O(n*m^2)#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong#defineinf1e18constintN=105;constintM=505;intc[N],v[N],in[N];//c:软件容量 v:软件价值 in:入度intdfn[N],low[N],stk[N];intscc[N],ins[N],cost[N],val[N];//scc:每个点所在的强连通分量编号//cost:强连通分量的容量 val:强连通分量的价值intdp[N][M];//dp[i][j] 以i为根的子树,选择i的前提下背包容量为j的最大价值vector<int>adj[N],ad[N];intn,m,ti,tp,id;voidtarjan(intu){dfn[u]=low[u]=++ti;stk[++tp]=u;ins[u]=1;for(intv:adj[u]){if(!dfn[v]){tarjan(v);low[u]=min(low[u],low[v]);}elseif(ins[v]){low[u]=min(low[u],dfn[v]);}}if(low[u]==dfn[u]){id++;do{intx=stk[tp];scc[x]=id;ins[x]=0;cost[id]+=c[x];val[id]+=v[x];}while(stk[tp--]!=u);}}voiddfs(intu){if(cost[u]>m)//父节点的容量已经超过整个背包容量,直接放弃这棵子树return;dp[u][cost[u]]=val[u];//先选择父节点(这棵子树的根节点)for(intv:ad[u]){dfs(v);//递归收集子树的情况for(intj=m;j>=cost[u];j--)//倒着枚举背包容量,保证只选择该子树一次{for(inti=0;i<=j-cost[u];i++)//枚举可以分配给这棵子树的容量{dp[u][j]=max(dp[u][j],dp[u][j-i]+dp[v][i]);}}}}voidsolve(){cin>>n>>m;for(inti=1;i<=n;i++)cin>>c[i];for(inti=1;i<=n;i++)cin>>v[i];for(inti=1;i<=n;i++){intx;cin>>x;if(x==0)continue;adj[x].push_back(i);}for(inti=1;i<=n;i++){if(!dfn[i])tarjan(i);}for(intu=1;u<=n;u++){inta=scc[u];for(intv:adj[u]){intb=scc[v];if(a==b)continue;ad[a].push_back(b);in[b]++;}}for(inti=1;i<=id;i++){if(in[i]==0){ad[0].push_back(i);}}for(inti=1;i<=id;i++){sort(ad[i].begin(),ad[i].end());ad[i].erase(unique(ad[i].begin(),ad[i].end()),ad[i].end());}dfs(0);cout<<dp[0][m]<<endl;}signedmain(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);intT=1;// cin >> T;while(T--){solve();}return0;}
http://www.jsqmd.com/news/1250250/

相关文章:

  • Pixel-Perfect Depth:单目深度估计的扩散模型与Transformer融合技术
  • 想发SCI,先把读文献这关过了
  • 上海黄金回收市场深度调研,不同渠道报价差距真相揭秘 - 日常比对手册
  • 2026年马氏体不锈钢渗硼加工行业解析:代表性品牌推荐与选型指南 - 资讯快报
  • mybatisplus Enum枚举,@JsonValue / @JsonCreator简单使用
  • 国家级制造业单项冠军申报核心要素及实操要点
  • AIGC检测多少算合格?2026年高校标准汇总,附降AI痕迹实测攻略
  • 真免费无套路✅2026论文查重避坑指南!PaperXie每日免费查重完胜全网
  • 某企业 APP 自动化测试 POC:AI 智能体能否真正完成测试执行闭环?
  • 基于 Django + PyTorch 的中文字体识别系统
  • 上海高端搬家机构品牌推荐 - 品牌推广大师
  • 2026追剧家庭零食品牌选型指南:正规合规服务商实力盘点+全链路合作避坑FAQ全解析 - U渠道
  • 靠谱指南,贵阳长途转运非急救救护车出租,转运安全保障细则全解读 - 资讯快报
  • 十分钟搞懂RAG检索增强生成核心原理、落地卡点与优化技巧
  • 告别卡顿!5款电脑看图神器实测推荐
  • 网络一切正常但就是打不开某个特定网站,问题出在哪?
  • 多层感知机的原理和应用场景
  • 成功上线Salesforce迁移项目
  • 鸿蒙新特性:@ohos.telephony.radio/sim 蜂窝网络实验室实战 —— 无线技术、信号强度与 SIM 卡
  • 深入解析TMS320C5x DSP架构:哈佛结构、外设协同与低功耗设计实战
  • 2026梧州黄金回收白银回收铂金回收工商备案可查全城上门回收旧金老店联系方式推荐
  • Linux Makefile 超全详解:从原理、语法到企业级实战
  • TMS320C6418 DSP时序参数深度解析:从理论到硬件设计实践
  • 2026济南除甲醛检测口碑榜:认准这几家才放心 - 资讯快报
  • 2026 视频去水印在线工具有哪些?免费在线网站怎么选 - 免费软件工具方法教程
  • 给 AI 装上“资深工程师大脑“:Superpowers 方法论全解
  • SEO团队职能转型:如何用见川GEO实现生成式搜索优化?
  • 全球80000余座大型国际机场、地区性通航机场、水上飞机起降点分布矢量数据
  • 杭州工业设备服务GEO城市合伙人选型推荐哪家靠谱?从技术底座到合伙人权益的七维深度拆解 - 小随科技
  • 2026成都装修公司存量房整装甄选指南:旧房翻新实测对比(附6大品牌筛选标准) - 资讯快报