[HAOI2010]软件安装(树形背包,tarjan缩点)
题目描述
现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi。我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大)。
但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j)。幸运的是,一个软件最多依赖另外一个软件。如果一个软件不能正常工作,那么它能够发挥的作用为0。
我们现在知道了软件之间的依赖关系:软件i依赖软件Di。现在请你设计出一种方案,安装价值尽量大的软件。一个软件只能被安装一次,如果一个软件没有依赖则Di=0,这时只要这个软件安装了,它就能正常工作。
输入输出格式
输入格式:
第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 )
输出格式:
一个整数,代表最大价值
思路:
望过去满眼的树形DP
和前面写的选课一模一样,只是cost需要输入
但很显然,你会这样
为什么呢?
后来想了半天,才发现
如果1依赖于2,2依赖于2,3依赖于1的化,这几个个点其实也能选,不过要选得一起选
所以,我们要用tarjan来缩点
把所有满足上图关系的点变为一个新点,并且与0连边即可
Q:环套树怎么办?
因为一个点只唯一依赖另一个点,所以入边一定为1
所以一定是环到树,不可能树到环,所以缩点没问题
懒了一下,用了stl
代码:
- // luogu-judger-enable-o2
- #include<iostream>
- #include<stack>
- #include<cstdio>
- #include<cstring>
- #include<cstdlib>
- #define rii register int i
- #define rij register int j
- #define rik register int k
- using namespace std;
- const int N=;const int M=;
- struct E{
- int to,nxt;
- }ed[N<<];
- int H[N<<],cnt;
- stack<int>sta;
- bool ins[N];
- int dp[N][M],v[N],w[N],d[N];
- int tot,dfn[N],low[N];
- int num,col[N],fv[N],fw[N];
- int n,m,rd[N];
- void add(int x,int y)
- {
- cnt++;
- ed[cnt].to=y;
- ed[cnt].nxt=H[x];
- H[x]=cnt;
- return;
- }
- void read(int &in)
- {
- int x=,f=;
- char ch;
- for(ch=getchar();(ch<''||ch>'')&&ch!='-';ch=getchar());
- if(ch=='-')
- {
- f=-;
- ch=getchar();
- }
- while(ch>=''&&ch<='')
- {
- x=(x<<)+(x<<)+ch-'';
- ch=getchar();
- }
- in=x*f;
- return;
- }
- void tarjan(int x)
- {
- dfn[x]=low[x]=++tot;
- ins[x]=true;sta.push(x);
- int t,k;
- for(rii=H[x];i;i=ed[i].nxt)
- {
- t=ed[i].to;
- if(!dfn[t])
- {
- tarjan(t);
- low[x]=min(low[x],low[t]);
- }
- else if(ins[t])
- {
- low[x]=min(low[x],dfn[t]);
- }
- }
- if(low[x]==dfn[x])
- {
- num++;
- do
- {
- k=sta.top();
- sta.pop();
- col[k]=num;
- fw[num]+=w[k];
- fv[num]+=v[k];
- ins[k]=false;
- }
- while(k!=x);
- }
- return;
- }
- void dfs(int x)
- {
- for(rii=fw[x];i<=m;i++)
- {
- dp[x][i]=fv[x];
- }
- int t;
- for(rii=H[x];i;i=ed[i].nxt)
- {
- t=ed[i].to;
- dfs(t);
- for(rij=m-fw[x];j>=;j--)
- {
- for(rik=;k<=j;k++)
- {
- dp[x][j+fw[x]]=max(dp[x][j+fw[x]],dp[x][j+fw[x]-k]+dp[t][k]);
- }
- }
- }
- return;
- }
- int main()
- {
- // freopen("software.in","r",stdin);
- // freopen("software.out","w",stdout);
- read(n);
- read(m);
- for(rii=;i<=n;i++)
- {
- read(w[i]);
- }
- for(rii=;i<=n;i++)
- {
- read(v[i]);
- }
- for(rii=;i<=n;i++)
- {
- read(d[i]);
- if(d[i])
- {
- add(d[i],i);
- }
- }
- for(rii=;i<=n;i++)
- {
- if(!dfn[i])
- {
- tarjan(i);
- }
- }
- memset(H,,sizeof(H));
- cnt=;
- for(rii=;i<=n;i++)
- {
- if(col[i]!=col[d[i]]&&d[i])
- {
- add(col[d[i]],col[i]);
- rd[col[i]]++;
- }
- }
- for(rii=;i<=num;i++)
- {
- if(!rd[i])
- {
- add(num+,i);
- }
- dfs(num+);
- }
- printf("%d\n",dp[num+][m]);
- return ;
- }
- // luogu-judger-enable-o2
- #include<iostream>
- #include<stack>
- #include<cstdio>
- #include<cstring>
- #include<cstdlib>
- #define rii register int i
- #define rij register int j
- #define rik register int k
- using namespace std;
- const int N=;const int M=;
- struct E{
- int to,nxt;
- }ed[N<<];
- int H[N<<],cnt;
- stack<int>sta;
- bool ins[N];
- int dp[N][M],v[N],w[N],d[N];
- int tot,dfn[N],low[N];
- int num,col[N],fv[N],fw[N];
- int n,m,rd[N];
- void add(int x,int y)
- {
- cnt++;
- ed[cnt].to=y;
- ed[cnt].nxt=H[x];
- H[x]=cnt;
- return;
- }
- void read(int &in)
- {
- int x=,f=;
- char ch;
- for(ch=getchar();(ch<''||ch>'')&&ch!='-';ch=getchar());
- if(ch=='-')
- {
- f=-;
- ch=getchar();
- }
- while(ch>=''&&ch<='')
- {
- x=(x<<)+(x<<)+ch-'';
- ch=getchar();
- }
- in=x*f;
- return;
- }
- void tarjan(int x)
- {
- dfn[x]=low[x]=++tot;
- ins[x]=true;sta.push(x);
- int t,k;
- for(rii=H[x];i;i=ed[i].nxt)
- {
- t=ed[i].to;
- if(!dfn[t])
- {
- tarjan(t);
- low[x]=min(low[x],low[t]);
- }
- else if(ins[t])
- {
- low[x]=min(low[x],dfn[t]);
- }
- }
- if(low[x]==dfn[x])
- {
- num++;
- do
- {
- k=sta.top();
- sta.pop();
- col[k]=num;
- fw[num]+=w[k];
- fv[num]+=v[k];
- ins[k]=false;
- }
- while(k!=x);
- }
- return;
- }
- void dfs(int x)
- {
- for(rii=fw[x];i<=m;i++)
- {
- dp[x][i]=fv[x];
- }
- int t;
- for(rii=H[x];i;i=ed[i].nxt)
- {
- t=ed[i].to;
- dfs(t);
- for(rij=m-fw[x];j>=;j--)
- {
- for(rik=;k<=j;k++)
- {
- dp[x][j+fw[x]]=max(dp[x][j+fw[x]],dp[x][j+fw[x]-k]+dp[t][k]);
- }
- }
- }
- return;
- }
- int main()
- {
- // freopen("software.in","r",stdin);
- // freopen("software.out","w",stdout);
- read(n);
- read(m);
- for(rii=;i<=n;i++)
- {
- read(w[i]);
- }
- for(rii=;i<=n;i++)
- {
- read(v[i]);
- }
- for(rii=;i<=n;i++)
- {
- read(d[i]);
- if(d[i])
- {
- add(d[i],i);
- }
- }
- for(rii=;i<=n;i++)
- {
- if(!dfn[i])
- {
- tarjan(i);
- }
- }
- memset(H,,sizeof(H));
- cnt=;
- for(rii=;i<=n;i++)
- {
- if(col[i]!=col[d[i]]&&d[i])
- {
- add(col[d[i]],col[i]);
- rd[col[i]]++;
- }
- }
- for(rii=;i<=num;i++)
- {
- if(!rd[i])
- {
- add(num+,i);
- }
- dfs(num+);
- }
- printf("%d\n",dp[num+][m]);
- return ;
[HAOI2010]软件安装(树形背包,tarjan缩点)的更多相关文章
- BZOJ2427:[HAOI2010]软件安装(树形DP,强连通分量)
Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和 ...
- HAOI2010软件安装(树形背包)
HAOI2010软件安装(树形背包) 题意 有n个物品,每个物品最多会依赖一个物品,但一个物品可以依赖于一个不独立(依赖于其它物品)的物品,且可能有多个物品依赖一个物品,并且依赖关系可能形成一个环.现 ...
- 【BZOJ2427】[HAOI2010]软件安装 Tarjan+树形背包
[BZOJ2427][HAOI2010]软件安装 Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为 ...
- bzoj 2427 [HAOI2010]软件安装 Tarjan缩点+树形dp
[HAOI2010]软件安装 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2029 Solved: 811[Submit][Status][Dis ...
- Tarjan+树形DP【洛谷P2515】[HAOI2010]软件安装
[洛谷P2515][HAOI2010]软件安装 题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得 ...
- [HAOI2010]软件安装(Tarjan,树形dp)
[HAOI2010]软件安装 题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可 ...
- BZOJ_2427_[HAOI2010]软件安装_tarjan+树形DP
BZOJ_2427_[HAOI2010]软件安装_tarjan+树形DP 题意: 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁 ...
- [BZOJ2427][HAOI2010]软件安装(Tarjan+DP)
2427: [HAOI2010]软件安装 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1987 Solved: 791[Submit][Statu ...
- bzoj2427:[HAOI2010]软件安装(Tarjan+tree_dp)
2427: [HAOI2010]软件安装 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1053 Solved: 424[Submit][Statu ...
- 【BZOJ2427】[HAOI2010]软件安装(动态规划,Tarjan)
[BZOJ2427][HAOI2010]软件安装(动态规划,Tarjan) 题面 BZOJ 洛谷 题解 看到这类题目就应该要意识到依赖关系显然是可以成环的. 注意到这样一个性质,依赖关系最多只有一个, ...
随机推荐
- 重构指南 - 封装集合(Encapsulate Collection)
封装就是将相关的方法或者属性抽象成为一个对象. 封装的意义: 对外隐藏内部实现,接口不变,内部实现自由修改. 只返回需要的数据和方法. 提供一种方式防止数据被修改. 更好的代码复用. 当一个类的属性类 ...
- PAT 1042 Shuffling Machine
#include <cstdio> #include <cstdlib> #include <vector> using namespace std; ] = {' ...
- 1729 单词查找树 2000年NOI全国竞赛
1729 单词查找树 2000年NOI全国竞赛 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 在进行文法分析的 ...
- hook_myhook.api.php文件什么用
看源文件的时候发现有个user.api.php文件,里面定义了一个新的钩子,$hook_user_categories,但是,drupal核心里面没有,我推测是自定义 的钩子函数,然后在*.modul ...
- alpinelinux
https://wiki.alpinelinux.org/wiki/Tutorials_and_Howtos https://nixos.org/nix/manual/#ch-installing-b ...
- ArcGIS Enterprise 10.5.1 静默安装部署记录(Centos 7.2 minimal)- 6、总结
安装小结 安装完成后,首先我们需要将Datastore托管给Server,再将Server托管给Portal以此来完成整个单机版Enterprise 部署流程.为了测试流程是否正确,我们可以采用上传一 ...
- jquery简介(一)
摘要:简要介绍jquery的起源,以及为什么需要使用jquery. jquery的优点 jquery体量小,加载速度快,其本身具有的功能使JavaScript应用程序开发人员的工作变得分外轻松.其中最 ...
- matlab练习程序(弧形、圆柱投影的复原)
前一段介绍了从矩形图像到圆柱的正向投影,看这里和这里.今天介绍如何从已经投影的图像反映射到原图像上. 本来此种变换一定是需要数学公式的,不过这里只是用了一个很简单的方式来完成反映射. 具体就把每一列有 ...
- 一个简单的 HTML 文档,带有最基本的必需的元素
<html> <head> <title>文档的标题</title> </head> <body> 文档的内容... ... & ...
- BIEE入门(二)物理层的定义
使用BIEE的第一步是使用admintool去建立一个多维数据模型,而建立多维数据模型的第一步则是建立物理层,请注意因为BIEE本身并不存 储数据,所以所谓BIEE物理层的意义是需要在BIEE里建立各 ...