博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj2427: [HAOI2010]软件安装
阅读量:5340 次
发布时间:2019-06-15

本文共 2559 字,大约阅读时间需要 8 分钟。

Description

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

但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j)。幸运的是,一个软件最多依赖另外一个软件。如果一个软件不能正常工作,那么它能够发挥的作用为0。
我们现在知道了软件之间的依赖关系:软件i依赖软件Di。现在请你设计出一种方案,安装价值尽量大的软件。一个软件只能被安装一次,如果一个软件没有依赖则Di=0,这时只要这个软件安装了,它就能正常工作。

 

Input

第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 )

 

Output

一个整数,代表最大价值。

 

Sample Input

3 10
5 5 6
2 3 4
0 1 1

Sample Output

5

HINT

 

Source

 
题解:
先tarjan缩下点,使其变成一棵树,然后我们就可以进行树上背包了
设f[u][i]表示选到u,用了空间i,得到的最大收益是多少
O(nm
2)的转移显然,但其实可以优化到O(nm)
设u的一个儿子是v,则我们可以把f[u]作为初始状态直接付给f[v],然后就可以减少一个m的转移复杂度
注意把f[u]作为初始状态直接付给f[v]时,f[v]的第二维有下限(就是v及其所有祖先所占的空间和)
code:
1 #include
2 #include
3 #include
4 #include
5 #include
6 using namespace std; 7 char ch; 8 bool ok; 9 void read(int &x){10 ok=0;11 for (ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;12 for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());13 if (ok) x=-x;14 }15 const int maxn=105;16 const int maxm=505;17 const int inf=1010580541;18 int n,m,a[maxn],b[maxn],x,ans;19 int f[maxn][maxm],g[maxm];20 int idx,dfn[maxn],low[maxn],stack[maxn],top,cnt,bel[maxn],siz[maxn],val[maxn],deg[maxn];21 bool in[maxn],bo[maxn];22 struct Graph{23 int tot,now[maxn],son[maxn],pre[maxn];24 void put(int a,int b){pre[++tot]=now[a],now[a]=tot,son[tot]=b;}25 void dfs(int u){26 dfn[u]=low[u]=++idx,stack[++top]=u,in[u]=1;27 for (int p=now[u],v=son[p];p;p=pre[p],v=son[p])28 if (!dfn[v]) dfs(v),low[u]=min(low[u],low[v]);29 else if (in[v]) low[u]=min(low[u],dfn[v]);30 if (dfn[u]==low[u]){31 int v; ++cnt;32 do{v=stack[top--],bel[v]=cnt,siz[cnt]+=a[v],val[cnt]+=b[v],in[v]=0;}while (u!=v);33 }34 }35 /*void dp(int u){36 bo[u]=1;37 memset(f[u],195,sizeof(f[u]));38 f[u][siz[u]]=val[u];39 for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]) if (!bo[v]){40 dp(v);41 memcpy(g,f[u],sizeof(g));42 for (int i=0;i<=m;i++) for (int j=m;j>=i;j--) g[j]=max(g[j],f[v][i]+f[u][j-i]);43 memcpy(f[u],g,sizeof(g));44 }45 f[u][0]=max(f[u][0],0);46 }*/47 /*void dp(int u,int m){48 //cout<
<<' '<
<

 

转载于:https://www.cnblogs.com/chenyushuo/p/5499649.html

你可能感兴趣的文章
Native C++中调用C++/C#/VB托管程序集(用C++保护.NET程序)
查看>>
01.02
查看>>
给力的 Google HTML5 训练营(HTML5 Drag&Drop 拖拽、FileReader实例教程
查看>>
用Redis bitmap统计活跃用户、留存(转)
查看>>
(转)Android之发送短信的两种方式
查看>>
Swift还是Objective-C,你怎么选择
查看>>
Codeforces Round #562 (Div. 2)
查看>>
Python里面这些点,据说80%的新手都会一脸懵逼
查看>>
【DP+拓扑】关键子工程
查看>>
Jenkins创建job时Check-out Strategy各个选项详细说明(含图)
查看>>
js android页面被挂起问题解决
查看>>
1-4-13:分段函数
查看>>
DAL 层引用 System.Net.Http ,引发的一阵心慌
查看>>
写在最前面的话
查看>>
C语言计算字符串子串出现的次数
查看>>
【Object-C】类Class
查看>>
Session
查看>>
bzoj 4034: [HAOI2015]树上操作 (树剖+线段树 子树操作)
查看>>
【System】shell 实现 bat 的pause功能
查看>>
Codeforces ZeptoLab Code Rush 2015 D.Om Nom and Necklace(kmp)
查看>>