点此看题面

大致题意: 有\(N\)个软件,每个软件有至多一个依赖以及一个所占空间大小\(W_i\),只有当一个软件的直接依赖和所有的间接依赖都安装了,它才能正常工作并造成\(V_i\)的价值。求在容量为\(M\)时的最大价值和。

大致思路

比较显然是树上背包

但是,这题中可能会出现,因此我们要先用\(Tarjan\)来缩点。

还要注意,缩完点后的图是一个森林,因此我们需要再人为建一个根,将其向每棵树的根连一条边,这样就可以直接树形\(DP\)了。

主要是注意细节啊。

代码

#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define Gmax(x,y) (x<(y)&&(x=(y)))
#define Gmin(x,y) (x>(y)&&(x=(y)))
#define abs(x) ((x)<0?-(x):(x))
#define swap(x,y) (x^=y^=x^=y)
#define uint unsigned int
#define LL long long
#define ull unsigned long long
#define INF 1000000000
#define N 100
#define M 500
#define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
using namespace std;
int n,m,ee,fa[N+5],w[N+5],v[N+5],lnk[N+5],deg[N+5];
struct edge
{
int to,nxt;
}e[N+5];
class Class_FIO
{
private:
#define Fsize 100000
#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,Fsize,stdin),A==B)?EOF:*A++)
#define pc(ch) (void)(FoutSize<Fsize?Fout[FoutSize++]=ch:(fwrite(Fout,1,FoutSize,stdout),Fout[(FoutSize=0)++]=ch))
int f,FoutSize,Top;char ch,Fin[Fsize],*A,*B,Fout[Fsize],Stack[Fsize];
public:
Class_FIO() {A=B=Fin;}
inline void read(int &x) {x=0,f=1;while(!isdigit(ch=tc())) f=ch^'-'?1:-1;while(x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));x*=f;}
inline void write(int x) {if(!x) return pc('0');x<0&&(pc('-'),x=-x);while(x) Stack[++Top]=x%10+48,x/=10;while(Top) pc(Stack[Top--]);}
inline void clear() {fwrite(Fout,1,FoutSize,stdout),FoutSize=0;}
}F;
class Class_Tarjan//Tarjan缩点
{
private:
int d,Top,dfn[N+5],low[N+5],Stack[N+5],InStack[N+5];
public:
int cnt,col[N+5],Weight[N+5],Val[N+5];
inline bool Vis(int x) {return dfn[x];}
inline void Solve(int x,int lst=0)
{
register int i;
for(dfn[x]=low[x]=++d,InStack[Stack[++Top]=x]=1,i=lnk[x];i;i=e[i].nxt)
{
if(!dfn[e[i].to]) Solve(e[i].to,x),Gmin(low[x],low[e[i].to]);
else if(InStack[e[i].to]) Gmin(low[x],dfn[e[i].to]);
}
if(dfn[x]^low[x]) return;
Weight[col[x]=++cnt]=w[x],Val[cnt]=v[x],InStack[x]=0;
while(Stack[Top]^x) Weight[col[Stack[Top]]=cnt]+=w[Stack[Top]],Val[cnt]+=v[Stack[Top]],InStack[Stack[Top--]]=0;
--Top;
}
inline void ReBuild()//重新建图
{
register int i;
for(ee=0,i=1;i<=n;++i) lnk[i]=0;//清空原先的边
for(i=1;i<=n;++i) col[fa[i]]^col[i]&&(add(col[fa[i]],col[i]),++deg[col[i]]);//建新边
for(i=1;i<=cnt;++i) !deg[i]&&add(0,i);//将0号节点向每棵树的根连一条边
}
}T;
class Class_TreeDP//树形DP求解树上背包
{
private:
int f[N+5][M+5],g[N+5];
inline void DP(int x)
{
register int i,j,k,lim;
for(i=g[x]=T.Weight[x];i<=m;++i) f[x][i]=T.Val[x];
for(i=lnk[x];i;i=e[i].nxt) for(DP(e[i].to),g[x]+=g[e[i].to],j=min(m,g[x]);j>=T.Weight[x];--j)
for(k=1,lim=min(j-T.Weight[x],g[e[i].to]);k<=lim;++k) Gmax(f[x][j],f[x][j-k]+f[e[i].to][k]);
}
public:
inline void Solve() {DP(0),F.write(f[0][m]);}
}TreeDP;
int main()
{
register int i;
for(F.read(n),F.read(m),i=1;i<=n;++i) F.read(w[i]);
for(i=1;i<=n;++i) F.read(v[i]);
for(i=1;i<=n;++i) F.read(fa[i]),fa[i]&&add(fa[i],i);
for(i=1;i<=n;++i) if(!T.Vis(i)) T.Solve(i);
return T.ReBuild(),TreeDP.Solve(),F.clear(),0;
}

【BZOJ2427】[HAOI2010] 软件安装(缩点+树形DP)的更多相关文章

  1. bzoj2427 [HAOI2010]软件安装——缩点+树形DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2427 今天的考试题...好不容易一次写对了树形DP,却没发现有环的情况... 发现自己 ta ...

  2. 洛谷 P2515 [HAOI2010]软件安装(缩点+树形dp)

    题面 luogu 题解 缩点+树形dp 依赖关系可以看作有向边 因为有环,先缩点 缩点后,有可能图不联通. 我们可以新建一个结点连接每个联通块. 然后就是树形dp了 Code #include< ...

  3. [bzoj2427][HAOI2010]软件安装——强连通分量+树形DP

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

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

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

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

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

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

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

  7. BZOJ2427:[HAOI2010]软件安装(树形DP,强连通分量)

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

  8. [BZOJ2427]:[HAOI2010]软件安装(塔尖+DP)

    题目传送门 题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用${W}_{i}$的磁盘空间,它的价值为${V}_{i}$.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件 ...

  9. 题解【bzoj2427 [HAOI2010]软件安装】

    Description 现在我们的手头有\(N\)个软件,对于一个软件\(i\),它要占用\(W_i\)的磁盘空间,它的价值为\(V_i\).我们希望从中选择一些软件安装到一台磁盘容量为\(M\)计算 ...

  10. bzoj2427: [HAOI2010]软件安装

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

随机推荐

  1. Codeforces Round #517 (Div. 2, based on Technocup 2019 Elimination Round 2)D(思维,DP,字符串)

    #include<bits/stdc++.h>using namespace std;char c[2007][2007];char ans[4007];int s[2007][2007] ...

  2. MySQL主从配置实战笔记

    其实网上已经有关于MySQL主从复制的很丰富全面的资料了,这里写点东西主要是为了给自己加深印象. 复制原理 MySQL主从复制是内建的非常强大的功能,主要应用于数据备份,负载均衡等方面.因为配置相对比 ...

  3. 51nod1024(math+set)

    题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1024 题意:中文题诶- 思路:要是能求出a^b的值来就好了. ...

  4. 2017-10-24 NOIP模拟赛

    括号序列 (bracket) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK有一个括号序列,但这个序列不一定合法. 一个合法的括号序列如下: ()是合法 ...

  5. [转]黑幕背后的__block修饰符

    http://www.cocoachina.com/ios/20150106/10850.html 我们知道在Block使用中,Block内部能够读取外部局部变量的值.但我们需要改变这个变量的值时,我 ...

  6. python 3.x 安装问题及连接oracle数据库

    最近有用到python去处理一些问题,发现现在3已出来,遂用直接下3.7使用 发现问题还是有一点的 1. pip 会出现ssl问题 Could not install packages due to ...

  7. JAVAFX-6 面板总结

    说明:转至:https://www.cnblogs.com/lensener/p/7978225.html 便于集中看到这些文章 面板列表: Accordion 手风琴面板:就是一个折叠展开功能,一般 ...

  8. linux shell 脚本 历史文件清理脚本,按天,按月,清理前N天的历史文件,删除指定大小历史文件,历史文件归档清理

    不知道大家那有没有要清理的这个事情.需要清理目录历史文件.可能后续也会有很多其他地方需要清理历史文件,可能会用到. 我这两天空闲写了个脚本,清理比较方便,有要进行清理的大量历史文件的话可以用. 脚本用 ...

  9. linux 编程笔记 2

    1.使用create建立文件: #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include ...

  10. 查看Memcache运行状况

    Memcache Memcache是danga.com的一个开源项目,它是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的Hash表,能够用来存储各种格式的数据. 查看当前的me ...