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(nm2)的转移显然,但其实可以优化到O(nm)
设u的一个儿子是v,则我们可以把f[u]作为初始状态直接付给f[v],然后就可以减少一个m的转移复杂度
注意把f[u]作为初始状态直接付给f[v]时,f[v]的第二维有下限(就是v及其所有祖先所占的空间和)
code:
 #include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
char ch;
bool ok;
void read(int &x){
ok=;
for (ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=;
for (x=;isdigit(ch);x=x*+ch-'',ch=getchar());
if (ok) x=-x;
}
const int maxn=;
const int maxm=;
const int inf=;
int n,m,a[maxn],b[maxn],x,ans;
int f[maxn][maxm],g[maxm];
int idx,dfn[maxn],low[maxn],stack[maxn],top,cnt,bel[maxn],siz[maxn],val[maxn],deg[maxn];
bool in[maxn],bo[maxn];
struct Graph{
int tot,now[maxn],son[maxn],pre[maxn];
void put(int a,int b){pre[++tot]=now[a],now[a]=tot,son[tot]=b;}
void dfs(int u){
dfn[u]=low[u]=++idx,stack[++top]=u,in[u]=;
for (int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if (!dfn[v]) dfs(v),low[u]=min(low[u],low[v]);
else if (in[v]) low[u]=min(low[u],dfn[v]);
if (dfn[u]==low[u]){
int v; ++cnt;
do{v=stack[top--],bel[v]=cnt,siz[cnt]+=a[v],val[cnt]+=b[v],in[v]=;}while (u!=v);
}
}
/*void dp(int u){
bo[u]=1;
memset(f[u],195,sizeof(f[u]));
f[u][siz[u]]=val[u];
for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]) if (!bo[v]){
dp(v);
memcpy(g,f[u],sizeof(g));
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]);
memcpy(f[u],g,sizeof(g));
}
f[u][0]=max(f[u][0],0);
}*/
/*void dp(int u,int m){
//cout<<u<<' '<<m<<endl;
bo[u]=1;
for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]) if (!bo[v]){
for (int i=0;i<=m;i++) f[v][i]=f[u][i];
dp(v,m-siz[v]);
for (int i=siz[v];i<=m;i++) f[u][i]=max(f[u][i],f[v][i-siz[v]]+val[v]);
}
}*/
void dp(int u,int low){
bo[u]=;
for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]) if (!bo[v]){
for (int i=low;i<=m-siz[v];i++) f[v][i+siz[v]]=f[u][i]+val[v];
dp(v,low+siz[v]);
for (int i=low+siz[v];i<=m;i++) f[u][i]=max(f[u][i],f[v][i]);
}
}
}G1,G2;
int main(){
read(n),read(m);
for (int i=;i<=n;i++) read(a[i]);
for (int i=;i<=n;i++) read(b[i]);
for (int i=;i<=n;i++) read(x),G1.put(x,i);
for (int i=;i<=n;i++) if (!dfn[i]) G1.dfs(i);
for (int u=;u<=n;u++) for (int p=G1.now[u],v=G1.son[p];p;p=G1.pre[p],v=G1.son[p])
if (bel[u]!=bel[v]) G2.put(bel[u],bel[v]),deg[bel[v]]++;
for (int u=;u<=n;u++) if (!deg[bel[u]]) G2.put(bel[],bel[u]);
//G2.dp(bel[0]);
//G2.dp(bel[0],m);
G2.dp(bel[],);
for (int i=;i<=m;i++) ans=max(ans,f[bel[]][i]);
printf("%d\n",ans);
return ;
}

bzoj2427: [HAOI2010]软件安装的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  7. [BZOJ2427][HAOI2010]软件安装-tarjan缩点-树上dp

    <题面> 这个题真伤人 之前Tarjan和树规都没学好,吃了不少亏,仔仔细细的搞了一天,收获颇丰 先来一个Tarjan的链接:$\mathbb{O}$ 题目的数据比较友好: $dp$不对: ...

  8. BZOJ2427: [HAOI2010]软件安装 tarjan+树形背包

    分析: 一开始我以为是裸的树形背包...之后被告知这东西...可能有环...什么!有环! 有环就搞掉就就可以了...tarjan缩点...建图记得建立从i到d[i]之后跑tarjan,因为这样才能判断 ...

  9. [BZOJ2427][HAOI2010]软件安装(tarjan+树形DP)

    如果依赖关系出现环,那么对于一个环里的点,要么都选要么都不选, 所以每个环可以当成一个点,也就是强连通分量 然后就可以构造出一颗树,然后树形背包瞎搞一下就行了 注意要搞一个虚拟节点当根节点 Code ...

随机推荐

  1. Redis学习手册(String数据类型)

    一.概述: 字符串类型是Redis中最为基础的数据存储类型,它在Redis中是二进制安全的,这便意味着该类型可以接受任何格式的数据,如JPEG图像数据或Json对象描述信息等.在Redis中字符串类型 ...

  2. android中ListView点击和里边按钮点击不能同时生效问题解决

    今天遇到一个问题:android中ListView点击和里边button点击不能同时生效问题解决. 原因是: listView 在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得 ...

  3. careercup-递归和动态规划 9.1

    9.1 有个小孩正在上楼梯,楼梯有n阶台阶,小孩一次可以上1阶.2阶或3阶.实现一个方法,计算小孩有多少种上楼梯的方法. 解法: 我们可以采用自上而下的方式来解决这个问题.小孩上楼梯的最后一步,也就是 ...

  4. 常用数据库的驱动类/URL/默认端口

    常用数据库的驱动类/URL/默认端口 1.Oracle:     格式:     驱动:oracle.jdbc.driver.OracleDriver     URL:jdbc:oracle:thin ...

  5. ANT的安装和配置(windows)

    1.下载:到ANT官方网站http://ant.apache.org/下载最新版本,解压后即可.2.配置环境变量:我的电脑----属性-----高级----环境变量      如:ANT_HOME:C ...

  6. java中double四舍五入并设置小数点位数的问题

    本文系转载,原文地址:http://blog.csdn.net/star_huang/article/details/7639267 今天遇到个需要将一个double类型的数据保留小数点后两位的问题. ...

  7. ssh-add命令

    ssh-add命令是把专用密钥添加到ssh-agent的高速缓存中.该命令位置在/usr/bin/ssh-add ➜ ydoc git:(v2.0.0) ✗ sudo ssh-add ~/.ssh/i ...

  8. iOS tableview 静态表布局纪录

    今天使用了tableview静态表布局,纪录如下 1:使用tableview 静态表,必须是UITableViewController 2:Content 中选择 Static Cells 如下图 3 ...

  9. JUnit4简要说明

    单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证. 开发者编写一小段代码,用于检验被测代码的一个很小的.很明确的功能是否正确. 通常而言,一个单元测试是用于判断某个特定 ...

  10. Browser 对象

    Browser 对象 window对象表示浏览器中打开的窗口如果文档包含框架(iframe 或 iframe标签),浏览器会为HTML文档创建一个window对象,并为每个框架创建一个额外的windo ...