P2515 [HAOI2010]软件安装

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

考虑对 i 依赖 j 认为 ji 的父亲。那么就是图就是森林。对于一个点要搞它就必须搞这个点到链。

image
22.cnblogs.com/blog/1910062/202207/1910062-20220722203459948-261045732.png)

因为儿子共用 x>root 这条链,所以我们可以对于儿子都不收费最后再整体收一次费(因为要求 x 一定选),也就是最后再来值域向右平移即可。

注意下可能有环,当复习 tarjan 了。

最后森林对于每棵树合并下即可。

#include <bits/stdc++.h> #define pb push_back using namespace std; int rd() { int sum=0,f=1; char ch=getchar(); while(ch>'9'||ch<'0') { if(ch=='-') f=-1; ch=getchar(); } while(ch<='9'&&ch>='0') { sum=sum*10+ch-'0'; ch=getchar(); } return sum*f; } const int N=105,M=(int)(1e5+5),MX=(int)(1e3); vector<int>g[N]; int f[N][M],tmp[M],a[N],b[N],w[N],v[N],fa[N],n,m; void dfs(int x,int W) { for(int i=0;i<g[x].size();i++) { int y=g[x][i]; dfs(y,W+w[x]); int Wy=W+w[x]; for(int j=2*MX;j>=0;j--) { for(int k=0;k<=j;k++) { if(k+Wy>MX) break ; f[x][j]=max(f[x][j],f[y][k+Wy]+f[x][j-k]); } } } for(int i=0;i<=2*MX;i++) tmp[i]=f[x][i]; for(int i=0;i<=2*MX;i++) { if(i-W-w[x]>=0) f[x][i]=tmp[i-W-w[x]]+v[x]; else f[x][i]=0; } } int ff[M]; bool flag[N]; int dfn[N],low[N],id[N],tot,col; stack<int>s; void tarjan(int x) { dfn[x]=low[x]=++tot; s.push(x); flag[x]=1; for(int i=0;i<g[x].size();i++) { int y=g[x][i]; if(!dfn[y]) { tarjan(y); low[x]=min(low[x],low[y]); } else if(flag[y]) { low[x]=min(low[x],dfn[y]); } } if(low[x]==dfn[x]) { ++col; while(1) { int qwq=s.top(); s.pop(); id[qwq]=col; flag[qwq]=0; if(qwq==x) break ; } } } int du[N]; signed main() { n=rd(); m=rd(); for(int i=1;i<=n;i++) a[i]=rd(); for(int i=1;i<=n;i++) b[i]=rd(); for(int i=1;i<=n;i++) { fa[i]=rd(); if(fa[i]) g[fa[i]].pb(i); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;i++) g[i].clear(); for(int i=1;i<=n;i++) { if(!fa[i]) continue ; if(id[i]!=id[fa[i]]) g[id[fa[i]]].pb(id[i]),++du[id[i]]; } // for(int i=1;i<=n;i++) cout<<id[i]<<'\n'; for(int i=1;i<=n;i++) w[id[i]]+=a[i],v[id[i]]+=b[i]; for(int i=1;i<=col;i++) if(!du[i]) dfs(i,0); for(int i=1;i<=col;i++) { if(!du[i]) for(int j=m;j>=0;j--) { for(int k=0;k<=j;k++) { ff[j]=max(ff[j],f[i][k]+ff[j-k]); } } } cout<<ff[m]; return 0; }

__EOF__

本文作者F x o r G
本文链接https://www.cnblogs.com/xugangfan/p/16507938.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FxorG  阅读(37)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示