bzoj 2427 && codevs 1866 tarjian缩点+树形dp
来源:互联网 发布:sql 创建表 id 自增 编辑:程序博客网 时间:2024/06/16 00:44
【题意】
2427: [HAOI2010]软件安装
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 929 Solved: 371
[Submit][Status][Discuss]
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
5 5 6
2 3 4
0 1 1
Sample Output
5
【解题方法】观察样例容易知道,这是一堆点套着一个环,由于是有向图,可以缩点,缩点之后就是一个树形dp模板了,缩点不会,还特意去学了一下,可以参考这篇blog:点击打开链接
【AC 代码】
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn = 105;int n,m,tot,scc,ind,top;int v[maxn],w[maxn],sv[maxn],sw[maxn];int q[maxn],in[maxn*5];bool inq[maxn];int low[maxn],dfn[maxn],belong[maxn];int dp[maxn][maxn*5];int head1[maxn],head2[maxn];struct edge{ int to,next;}e1[maxn*5],e2[maxn*5];void init1(){ memset(head1,0,sizeof(head1)); tot=0;}void init2(){ memset(head2,0,sizeof(head2)); tot=0;}void addedge1(int u,int v){ e1[++tot].to=v,e1[tot].next=head1[u],head1[u]=tot;}void addedge2(int u,int v){ in[v]=1; e2[++tot].to=v,e2[tot].next=head2[u],head2[u]=tot;}void tarjian(int x){ int now=0; low[x]=dfn[x]=++ind; q[++top]=x;inq[x]=1; for(int i=head1[x]; i; i=e1[i].next){ int v=e1[i].to; if(!dfn[v]){ tarjian(v); low[x]=min(low[x],low[v]); }else if(inq[v]){ low[x]=min(low[x],dfn[v]); } } if(low[x]==dfn[x]){ scc++; while(now!=x){ now=q[top--];inq[now]=0; belong[now]=scc; sv[scc]+=v[now]; sw[scc]+=w[now]; } }}void rebuild(){ tot=0; for(int x=1; x<=n; x++) for(int i=head1[x]; i; i=e1[i].next) if(belong[e1[i].to]!=belong[x]) addedge2(belong[x],belong[e1[i].to]);}void dfs(int x){ for(int i=head2[x]; i; i=e2[i].next){ int v=e2[i].to; dfs(v); for(int j=m-sw[x]; j>=0; j--){ for(int k=0; k<=j; k++){ dp[x][j] = max(dp[x][j],dp[x][k]+dp[v][j-k]); } } } for(int j=m; j>=0; j--){ if(j>=sw[x]) dp[x][j]=dp[x][j-sw[x]]+sv[x]; else dp[x][j]=0; }}int main(){ scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) scanf("%d",&w[i]); for(int i=1; i<=n; i++) scanf("%d",&v[i]); init1(); for(int i=1; i<=n; i++){ int x; scanf("%d",&x); if(x) addedge1(x,i); } for(int i=1; i<=n; i++){ if(!dfn[i]) tarjian(i); } //init2(); rebuild(); for(int i=1; i<=scc; i++){ if(!in[i]) addedge2(scc+1,i); } dfs(scc+1); cout<<dp[scc+1][m]<<endl; return 0;}
0 0
- bzoj 2427 && codevs 1866 tarjian缩点+树形dp
- BZOJ 2427 /HAOI 2010 软件安装 tarjan缩点+树形DP
- bzoj 2427: [HAOI2010]软件安装(tarjan缩点+树形dp)
- poj1236 Network of School ( tarjian + 缩点 )
- BZOJ 2152: 聪聪可可(点分治/树形DP)
- Codevs 1378 选课 树形DP
- BZOJ 2427 软件安装 树形dp+tarjan
- BZOJ 2152 (树形DP)
- bzoj 3037(树形DP)
- bzoj 4027 树形dp
- bzoj 3573(树形DP)
- bzoj 4254 树形dp
- BZOJ 1369 树形DP
- BZOJ 4033 树形DP
- [学习]用tarjian算法求强连通分量,tarjian算法缩点[学习知识~]
- BZOJ 2427: [HAOI2010]软件安装 Tarjan缩点 + DP
- poj 2553 tarjian+缩点。。。强连通分量
- poj 2553 tarjian+缩点。。。强连通分量
- 第一章 Hello Word
- 5.3SVM实例1--python机器学习
- 资治通鉴-1 司马光的另类史记
- Android Universal Image Loader 源码分析
- 2016.08.16回顾
- bzoj 2427 && codevs 1866 tarjian缩点+树形dp
- 6.1神经网络--python机器学习
- jsp设置cookie的HTTPOnly属性
- 并查集和带权并查集
- 第二章 线程管理
- Android MVP实战——环境云API+Android实现天气预报查询(上)
- python文件操作
- MySQL 数据库简介+Vs2010链接数据库
- 华为交换机stp简单配置