洛谷 P2515 [HAOI2010]软件安装
2017-04-12 23:51
281 查看
题目描述
现在我们的手头有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 )
输出格式:
一个整数,代表最大价值
输入输出样例
输入样例#1:3 105 5 62 3 40 1 1
输出样例#1:
5
哈哈,又是一道好题!
思路还是比较好想的,先tarjan缩点,重新建图,原图从基环树变成树,做树形dp,然而本人比较弱,树形dp没有一次写对。
#include<iostream> #include<cstring> #include<cstdio> #include<stack> using namespace std; const int N=105; int n,m,cnt,dcnt,tim,d ,c ,w ,hd ,dfn ,low ,cc ,ww ,f [505],belong ,du ; bool ins ; stack<int>stk; struct edge { int to,nxt; }v ; void addedge(int x,int y) { v[++cnt].to=y; v[cnt].nxt=hd[x]; hd[x]=cnt; } void tarjan(int u) { dfn[u]=low[u]=++tim; ins[u]=1; stk.push(u); for(int i=hd[u];i;i=v[i].nxt) { if(!dfn[v[i].to]) { tarjan(v[i].to); low[u]=min(low[u],low[v[i].to]); } else if(ins[v[i].to]) low[u]=min(low[u],dfn[v[i].to]); } if(dfn[u]==low[u]) { ++dcnt; while(1) { int t=stk.top(); stk.pop(); ins[t]=0; belong[t]=dcnt; if(u==t) break; } } } void dp(int u,int fa) { for(int i=hd[u];i;i=v[i].nxt) if(v[i].to!=fa) { dp(v[i].to,u); for(int j=m-cc[u];j>=1;j--) for(int k=1;k<=j;k++) f[u][j]=max(f[u][j],f[u][j-k]+f[v[i].to][k]); } for(int i=m;i>=0;i--) if(i>=cc[u]) f[u][i]=f[u][i-cc[u]]+ww[u]; else f[u][i]=0; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&c[i]); for(int i=1;i<=n;i++) scanf("%d",&w[i]); for(int i=1;i<=n;i++) { scanf("%d",&d[i]); if(d[i]) addedge(d[i],i); } //缩点 for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); //重新建图 for(int i=1;i<=n;i++) cc[belong[i]]+=c[i],ww[belong[i]]+=w[i]; memset(hd,0,sizeof(hd)); cnt=0; for(int i=1;i<=n;i++) if(d[i]&&belong[d[i]]!=belong[i]) { addedge(belong[d[i]],belong[i]); du[belong[i]]++; } for(int i=1;i<=dcnt;i++) if(!du[i]) addedge(0,i); //树形dp dp(0,-1); printf("%d\n",f[0][m]); return 0; }
相关文章推荐
- 洛谷——P2515 [HAOI2010]软件安装
- 【洛谷P2515【HAOI2010】】软件安装
- Tarjan+树形DP【洛谷P2515】[HAOI2010]软件安装
- 洛谷 P2515 [HAOI2010]软件安装
- BZOJ2427 洛谷P2515 [HAOI2010]软件安装
- P2515 [HAOI2010]软件安装
- P2515 [HAOI2010]软件安装
- codevs1866(洛谷p2515)软件开发【HAOI2010】
- bzoj2427: [HAOI2010]软件安装
- bzoj2427: [HAOI2010]软件安装
- bzoj 2427[HAOI2010] 软件安装
- 【HAOI2010】【强连通分量】【树形动态规划】软件安装
- [HAOI2010] 软件安装
- [bzoj2427][HAOI2010]软件安装——强连通分量+树形DP
- [HAOI2010][BZOJ2427] 软件安装|tarjan|树型dp
- BZOJ 2427: [HAOI2010]软件安装( dp )
- 软件安装 [HAOI2010,Bzoj2427]
- [bzoj2427][HAOI2010]软件安装 Tarjan+树形DP
- 【bzoj2427】【HAOI2010】【软件安装】【缩点+dp】
- [HAOI2010]软件安装