zoukankan      html  css  js  c++  java
  • luogu 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

    缩点后树形dp
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn = 1007;
    
    inline int read() {
        int x=0,f=1;
        char c=getchar() ;
        while(c<'0'||c>'9'){ if(c=='-')f=-1;c=getchar();};
        while(c<='9'&&c>='0')x=x*10+c-'0',c=getchar();
        return x*f;
    }
    int w[maxn],v[maxn],n,m;
    struct node {
        int v,next;
    }edge[maxn*5],E[maxn*10];
    int num=0,N=0,H[maxn*2],head[maxn];
    inline void add_edge(int u,int v) {
        edge[++num].v=v;edge[num].next=head[u];head[u]=num;
    }
    inline void ADD(int u,int v) {
        E[++N].v=v;E[N].next=H[u];H[u]=N;
    }
    int dfn[maxn],low[maxn],color[maxn],color_cnt=0,stack[maxn],vul[maxn],wul[maxn];
    bool vis[maxn];int top;
    void tarjan(int x) {
        dfn[x]=low[x]=++num;
        vis[x]=1;stack[++top]=x;
        for(int i=head[x];i;i=edge[i].next) {
            int v=edge[i].v;
            if(!dfn[v]) {
                tarjan(v);
                low[x]=std::min(low[x],low[v]);
            }
            else if(vis[v]) low[x]=min(low[x],dfn[v]);
        }
        if(low[x]==dfn[x]) {
            color_cnt++;
            while(stack[top+1]!=x) {
                vis[stack[top]]=0;
                color[stack[top]]=color_cnt;
                vul[color_cnt]+=v[stack[top]];
                wul[color_cnt]+=w[stack[top]];top--;
            }
        }
    }
    int dp[maxn*2][maxn*5];
    void dfs(int x) {
        for(int i=wul[x];i<=m;++i) dp[x][i]=vul[x];
        for(int i=H[x];i;i=E[i].next) {
            int vv=E[i].v;
            dfs(vv);
            for(int j=m-wul[x];j>=0;j--) 
                for(int k=0;k<=j;k++) {
                    dp[x][j+wul[x]]=max(dp[x][j+wul[x]],dp[x][j+wul[x]-k]+dp[vv][k]);
                }
        }
        //for(int i=m;i>=0;i--) 
            //if(w[i]<=i)dp[x][i]=v[x];
            //else dp[x][i]=0;
    }
    bool rd[maxn*2];
    int main() {
        n=read(),m=read();
        for(int i=1;i<=n;++i) w[i]=read();
        for(int i=1;i<=n;++i) v[i]=read();
        for(int a,i=1;i<=n;++i) {
            a=read();
            if(a) add_edge(a,i);
        }num=0;
        //for(int i=1;i<=n;++i) {
        //    color[i]=i;
        //}
        for(int i=1;i<=n;++i) 
            if(!dfn[i])tarjan(i);
        for(int i=1;i<=n;++i) 
            for(int j=head[i];j;j=edge[j].next) {
                int vv=edge[j].v;
                if(color[i]!=color[vv]) {
                    ADD(color[i],color[vv]);
                    rd[color[vv]]=1;
                }
            }
        for(int i=1;i<=n;++i) {
            if(!rd[color[i]])ADD(0,color[i]);
        }
        dfs(0);
        printf("%d
    ",dp[0][m]);
        return 0;
    }
  • 相关阅读:
    java23中设计模式之策略模式
    java23中设计模式之模板模式
    java23中设计模式之备忘录模式
    java23中设计模式之命令模式
    java23中设计模式之中介者模式
    java23中设计模式之迭代器模式
    java23中设计模式只责任链模式
    web service -- jdk spring cxf ajax 开发(2)
    洛谷 P1566 加等式
    洛谷 P1439 【模板】最长公共子序列
  • 原文地址:https://www.cnblogs.com/sssy/p/8010506.html
Copyright © 2011-2022 走看看