【bzoj2427】【软件安装】tarjan缩点+树形依赖背包
2017-10-31 19:08
417 查看
(上不了p站我要死了,侵权度娘背锅)
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
wa了好久啊。。。在一些很细节的地方犯了很多低级错误
逐字比对之后才终于调出来,这wa率蹭蹭蹭就上去了。。T_T
其实这道题还是比较基础的。就是tarjan缩点之后,将所有树连向一个“超级根”,跑树上dp。
这个dp呢,是一个树形依赖背包。虽说是依赖背包,处理过后其实可以看做是一个分组背包。即,假设我们已处理出子树v占用m内存的最大价值,我们便可将子树v的各个值看做一个组,只能选择其中一种内存大小。而这道题的分组背包已经算是泛化物品了,外层for当前节点u的内存(从大到小),内层for子树v的内存大小(随便顺序)。
时间复杂度是o(n*m*m),可过
然后要附上wa的地方
看来是算法模板没有熟练,才会导致粗心的低级错误
完整代码(附wa点)
#include<stack> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=205; const int M=1005; stack<int> s; int n,m,ww ,vv ; int/*adde1*/ head1 ,end1[N*2],nxt1[N*2],hh1=0; int/*adde2*/ head2 ,end2[N*2],nxt2[N*2],hh2=0; int/*tarjan*/ dfn ,low ,idc=0,id ,cnt=0;bool exi ; int cos ,val ,in ; int/*dfs*/ dp [M]; void adde1(int a,int b){ hh1++; end1[hh1]=b; nxt1[hh1]=head1[a]; head1[a]=hh1; } void adde2(int a,int b){ hh2++; end2[hh2]=b; nxt2[hh2]=head2[a]; head2[a]=hh2; } void tarjan(int u){ dfn[u]=low[u]=++idc; s.push(u); exi[u]=1; for(int i=head1[u];i;i=nxt1[i]){ int v=end1[i]; if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]); } else if(exi[v]) low[u]=min(low[u],low[v]); } if(low[u]==dfn[u]){ cnt++; int tmp; while(s.top()!=u&&(!s.empty())){ tmp=s.top();s.pop(); id[tmp]=cnt; exi[tmp]=0; } if(s.top()==u){ s.pop(); id[u]=cnt; exi[u]=0;//最后在处理u时忘了。。 } } } void dfs(int u){//printf("%d ",u); dp[u][0]=0; for(int i=head2[u];i;i=nxt2[i]){ int v=end2[i]; dfs(v); for(int k=m-cos[u];k>=0;k--){//用了两次i,就导致了混乱 for(int j=k;j>=0;j--){ dp[u][k]=max(dp[u][k],dp[u][k-j]+dp[v][j]); } } } for(int j=m;j>=0;j--){ if(j-cos[u]>=0) dp[u][j]=dp[u][j-cos[u]]+val[u]; else dp[u][j]=0; } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&ww[i]); for(int i=1;i<=n;i++) scanf("%d",&vv[i]); int d; for(int i=1;i<=n;i++){ scanf("%d",&d); if(d) adde1(d,i); } while(!s.empty()) s.pop(); for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(int u=1;u<=n;u++){ cos[id[u]]+=ww[u],val[id[u]]+=vv[u]; for(int i=head1[u];i;i=nxt1[i]){ int v=end1[i]; if(id[u]!=id[v]) adde2(id[u],id[v]),in[id[v]]++; } } for(int i=1;i<=cnt;i++) if(!in[i]) adde2(0,i); memset(dp,-27,sizeof(dp)); dfs(0); int ans=0; for(int i=1;i<=m;i++) ans=max(ans,dp[0][i]); printf("%d\n",ans); return 0; }
总结:
1、像tarjan这种模板类型的要烂熟于心
相关文章推荐
- 【bzoj2427】【软件安装】tarjan缩点+树形依赖背包
- BZOJ 2427 软件安装 (tarjan 树形依赖背包)
- [BZOJ2427] 软件安装 tarjan缩点+树形背包
- bzoj2427 [HAOI2010]软件安装 ( 树形背包 + tarjan )
- 【BZOJ2427】【HAOI2010】软件安装 tarjan+树形背包DP
- BZOJ2427 浅谈TARJAN缩点 和 树形依赖背包动态规划
- [BZOJ2427][HAOI2010]软件安装(Tarjan+树形&背包DP)
- BZOJ 2427 /HAOI 2010 软件安装 tarjan缩点+树形DP
- bzoj 2427: [HAOI2010]软件安装(tarjan缩点+树形dp)
- BZOJ 2427 /HAOI 2010 软件安装 tarjan缩点+树形DP
- [BZOJ2427]软件安装-tarjan强连通+树形背包
- 【BZOJ2427】[HAOI2010]软件安装 Tarjan+树形背包
- BZOJ 2427 软件安装 树形dp+tarjan
- BZOJ 2427 [HAOI2010]软件安装 | 这道树形背包裸题严谨地证明了我的菜
- [bzoj2427][HAOI2010]软件安装(树形dp+tarjan)
- 【bzoj2427】[HAOI2010]软件安装 Tarjan+树形背包dp
- [BZOJ]2427 软件安装 O(nm)树形背包
- 【BZOJ-2427】软件安装 Tarjan + 树形01背包
- BZOJ 2427: [HAOI2010]软件安装|树形动规|tarjan
- BZOJ 2427: [HAOI2010]软件安装 Tarjan缩点 + DP