zoukankan      html  css  js  c++  java
  • bzoj2427: [HAOI2010]软件安装

    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

    HINT

    Source


    思路:树形背包。先把环缩掉,然后把所有树的根接到一个新的根上,就可以做了。设f[i][j]为:i的子树费用为j时所能得到的最大价值。
    f[i][j]=max(f[son[i]][k]+f[i][j-k-w[i]]+v[i])。
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    const int maxn=110,maxm=510;
    using namespace std;
    int n,m,w[maxn],v[maxn],sw[maxn],sv[maxn],f[maxn][maxm],dfn[maxn],low[maxn],bel[maxn],sta[maxn],top,in[maxn],tim,bcnt;
    int pre[maxn],now[maxn],son[maxn],pre2[maxn],now2[maxn],son2[maxn],tot;
    bool bo[maxn];
    void add(int a,int b){pre[++tot]=now[a],now[a]=tot,son[tot]=b;}
    void add2(int a,int b){in[b]++,pre2[++tot]=now2[a],now2[a]=tot,son2[tot]=b;}
    
    void tarjan(int x){
    	low[x]=dfn[x]=++tim,sta[++top]=x,bo[x]=1;
    	for (int y=now[x];y;y=pre[y]){
    		if (!dfn[son[y]]) tarjan(son[y]),low[x]=min(low[x],low[son[y]]);
    		else if (bo[son[y]]) low[x]=min(low[x],dfn[son[y]]);
    	}
    	if (low[x]==dfn[x]){
    		int xx=0;bcnt++;
    		while (xx!=x){
    			xx=sta[top--],bel[xx]=bcnt,bo[xx]=0;
    			sw[bcnt]+=w[xx],sv[bcnt]+=v[xx];
    		}
    	}
    }
    
    void init(){
    	tot=0;
    	for (int x=1;x<=n;x++)
    		for (int y=now[x];y;y=pre[y])
    			if (bel[x]!=bel[son[y]])
    				add2(bel[x],bel[son[y]]);
    	for (int i=1;i<=bcnt;i++)
    		if (!in[i]) add2(bcnt+1,i);
    }
    
    void Dp(int x){
    	for (int y=now2[x];y;y=pre2[y]){
    		Dp(son2[y]);
    		for (int j=m-sw[x];j>=0;j--)
    			for (int k=0;k<=j;k++)
    				f[x][j]=max(f[x][j],f[son2[y]][j-k]+f[x][k]);
    	}
    	for (int j=m;j>=sw[x];j--) f[x][j]=f[x][j-sw[x]]+sv[x];
    	for (int j=0;j<sw[x];j++) f[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]);
    	for (int i=1,x;i<=n;i++){scanf("%d",&x);if (x) add(x,i);}
    	for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i);
    	
    	init(),Dp(bcnt+1);//for (int i=1;i<=n;i++) printf("%d
    ",bel[i]);
    	printf("%d
    ",f[bcnt+1][m]);
    	return 0;
    }


  • 相关阅读:
    HDU 4024 Dwarven Sniper’s hunting(数学公式 或者是二分)
    二分图最大匹配总结
    HDU 4022 Bombing (STL应用)
    HDU 1847 Good Luck in CET4 Everybody!(组合博弈)
    HDU 1556 Color the ball(树状数组)
    HDU 4023 Game(博弈)
    HDU 1406 完数(水题)
    HDU 4021 24 Puzzle
    Oracle 多表查询优化
    【编程之美】字符串移位包含的问题(续)
  • 原文地址:https://www.cnblogs.com/thythy/p/5493583.html
Copyright © 2011-2022 走看看