zoukankan      html  css  js  c++  java
  • 洛谷 P2515 [HAOI2010]软件安装

    题目描述

    现在我们的手头有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 10
    5 5 6
    2 3 4
    0 1 1
    输出样例#1:
    5

     思路:tarjin缩点+树形DP

    错因:MLE

    #include<map>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define N 10001
    #define M 2501
    using namespace std;
    map<int,int>ma[N];
    int n,m,K;
    int tot,top;
    int tim,sum,sumcol;
    int col[N],kk[N],vval[N];
    int to[N],net[N],head[N];
    int k[N],val[N],f[N][M],dp[M];
    int dad[N],lchild[N],rchild[N];
    int vis[N],dis[N],low[N],stack[N],visstack[N];
    void add(int u,int v){
        to[++tot]=v;net[tot]=head[u];head[u]=tot;
    }
    void tarjin(int now){
        dis[now]=low[now]=++tim;
        vis[now]=1;
        stack[++top]=now;
        visstack[now]=1;
        for(int i=head[now];i;i=net[i])
            if(visstack[to[i]])
                low[now]=min(low[now],dis[to[i]]);
            else if(!vis[to[i]]){
                tarjin(to[i]);
                low[now]=min(low[now],low[to[i]]);
            }
        if(low[now]==dis[now]){
            sumcol++;
            col[now]=sumcol;
            while(stack[top]!=now){
                col[stack[top]]=sumcol;
                visstack[stack[top]]=0;
                top--;
            }
            visstack[now]=0;
            top--;
        }
    }
    int dfs(int i,int j){
        if(i>n||i<1||j>K||j<1)    return 0;
        if(f[i][j])    return f[i][j];
        for(int kkk=0;kkk<=j-kk[i];kkk++)
            f[i][j]=max(f[i][j],dfs(lchild[i],kkk)+dfs(rchild[i],j-kkk-kk[i])+vval[i]);
        f[i][j]=max(f[i][j],dfs(rchild[i],j));
        return f[i][j];
    }
    int main(){
        scanf("%d%d",&n,&K);
        for(int i=1;i<=n;i++)    scanf("%d",&k[i]);
        for(int i=1;i<=n;i++)    scanf("%d",&val[i]);
        for(int i=1;i<=n;i++){
            int x;
            scanf("%d",&x);
            if(x!=0)    add(x,i);
        }
        for(int i=1;i<=n;i++)
            if(!vis[i])    tarjin(i);
        for(int i=1;i<=n;i++)
            for(int j=head[i];j;j=net[j])
                if(col[i]!=col[to[j]])
                    if(ma[col[i]].find(col[to[j]])==ma[col[i]].end()){
                        ma[col[i]][col[to[j]]]=1;
                        dad[col[to[j]]]=col[i];
                    }
        for(int i=1;i<=sumcol;i++){
            int fa=dad[i];
            if(!lchild[fa])    lchild[fa]=i;
            else{
                fa=lchild[fa];
                while(rchild[fa])    fa=rchild[fa];
                rchild[fa]=i;
            }    
        }
        for(int i=1;i<=n;i++){
            kk[col[i]]+=k[i];
            vval[col[i]]+=val[i];
        }
        cout<<dfs(lchild[0],K);
    }
    细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
  • 相关阅读:
    xhtml+css (网站重构)
    一个典型的代码走查检查单
    谈谈单位时间内投票次数限制
    .NET性能优化方面的总结
    IE6.0、IE7.0 与 FireFox CSS
    vue3中使用 aggrid 表格组件
    基于predis高并发情况下实现频率控制的函数
    Redis之Centos下使用redis
    SVN的安装和使用
    Git配置教程
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/7543158.html
Copyright © 2011-2022 走看看