[HAOI2010] 软件安装
2017-01-21 11:30
363 查看
题目描述
现在我们的手头有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 )
输出格式
一个整数,代表最大价值。样例数据
样例输入
3 105 5 6
2 3 4
0 1 1
样例输出
5题目分析
根据题意,很容易想到金明的预算方案这道题,然后你就跪了,软件可以无限制地向上依赖,并不是主附件关系。然后你就想到了树形背包,然后就得了40分(我就是这样的),因为软件可以互相依赖,A依赖B,B依赖A,要么全部选,要么全部不选,因此可以进行Tarjan缩点。
然后就陷入无限调试状态。
再见
源代码
#include<algorithm> #include<iostream> #include<iomanip> #include<cstring> #include<cstdlib> #include<vector> #include<cstdio> #include<cmath> #include<queue> using namespace std; inline const int Get_Int() { int num=0,bj=1; char x=getchar(); while(x<'0'||x>'9') { if(x=='-')bj=-1; x=getchar(); } while(x>='0'&&x<='9') { num=num*10+x-'0'; x=getchar(); } return num*bj; } int Head[5005],TreeHead[5005],InDegree[5005],cnt=0,cnt2=0; struct Edge { int to,next; } Edge[5005],Tree[5005]; struct Software { int size,value; } a[5005],New[5005]; void AddEdge(int from,int to) { cnt++; Edge[cnt].to=to; Edge[cnt].next=Head[from]; Head[from]=cnt; } void AddNewEdge(int from,int to) { cnt2++; Tree[cnt2].to=to; Tree[cnt2].next=TreeHead[from]; TreeHead[from]=cnt2; } int step=0,Dfn[5005],Lowlink[5005],Stack[5005],top=0,Instack[5005],Belong[5005],SCC=0; void Tarjan(int Now) { step++; Lowlink[Now]=Dfn[Now]=step; Stack[++top]=Now; Instack[Now]=1; for(int i=Head[Now]; i; i=Edge[i].next) { int Next=Edge[i].to; if(!Dfn[Next]) { Tarjan(Next); Lowlink[Now]=min(Lowlink[Now],Lowlink[Next]); } else if(Instack[Next])Lowlink[Now]=min(Lowlink[Now],Dfn[Next]); } if(Lowlink[Now]==Dfn[Now]) { SCC++; int y; do { y=Stack[top--]; Belong[y]=SCC; New[SCC].size+=a[y].size; New[SCC].value+=a[y].value; Instack[y]=0; } while(y!=Now); } } int n,Size,map[505][505],f[505][505]; void TreeDp(int Now) { f[Now][New[Now].size]=New[Now].value; for(int i=TreeHead[Now]; i; i=Tree[i].next) { int Next=Tree[i].to; TreeDp(Next); for(int i=Size-New[Now].size; i>=0; i--) for(int j=0; j<=i; j++) f[Now][i+New[Now].size]=max(f[Now][i+New[Now].size],f[Now][i-j+New[Now].size]+f[Next][j]); } } int main() { n=Get_Int(); Size=Get_Int(); for(int i=1; i<=n; i++)a[i].size=Get_Int(); for(int i=1; i<=n; i++)a[i].value=Get_Int(); for(int i=1; i<=n; i++) { int x=Get_Int(); if(x!=0)AddEdge(x,i); } for(int i=1; i<=n; i++)if(!Dfn[i])Tarjan(i); for(int Now=1; Now<=n; Now++) for(int i=Head[Now]; i; i=Edge[i].next) { int Next=Edge[i].to; if(!map[Belong[Now]][Belong[Next]]&&Belong[Now]!=Belong[Next]) { map[Belong[Now]][Belong[Next]]=1; InDegree[Belong[Next]]++; AddNewEdge(Belong[Now],Belong[Next]); } } for(int i=1; i<=SCC; i++) if(InDegree[i]==0)AddNewEdge(SCC+1,i); SCC++; TreeDp(SCC); printf("%d\n",f[SCC][Size]); return 0; }
相关文章推荐
- BZOJ2427: [HAOI2010]软件安装
- 【BZOJ2427】【HAOI2010】软件安装
- bzoj 2427[HAOI2010] 软件安装
- bzoj2427: [HAOI2010]软件安装
- bzoj2427: [HAOI2010]软件安装
- |BZOJ 2427|树形DP|强连通分量|[HAOI2010]软件安装
- bzoj 2427: [HAOI2010]软件安装(tarjan缩点+树形dp)
- [HAOI2010][BZOJ2427] 软件安装|tarjan|树型dp
- BZOJ 2427: [HAOI2010]软件安装( dp )
- 软件安装 [HAOI2010,Bzoj2427]
- [HAOI2010]软件安装
- bzoj 2427 HAOI 2010 软件安装 (dp+tarjan缩点)
- bzoj 2427: [HAOI2010]软件安装
- 【bzoj2427】【HAOI2010】【软件安装】【缩点+dp】
- BZOJ 2427 HAOI 2010 软件安装 Tarjan+树上DP
- [bzoj2427][HAOI2010]软件安装——强连通分量+树形DP
- 【HAOI2010】【强连通分量】【树形动态规划】软件安装
- BOZJ 2427: [HAOI2010]软件安装 树形背包
- bzoj2427 [HAOI2010]软件安装
- 2427: [HAOI2010]软件安装