软件安装「HAOI2010」

题意

\(n\)个软件,每个软件都可能有一个依赖软件(换言之,不安装依赖软件就不能安装该软件)。每个软件都有自己的容量和价值,已知总容量,求最大价值。


思路

tarjan+树上背包裸题。

代码

#include <bits/stdc++.h>

using namespace std;

namespace StandardIO {

    template<typename T>inline void read (T &x) {
        x=0;T f=1;char c=getchar();
        for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
        for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
        x*=f;
    }

    template<typename T>inline void write (T x) {
        if (x<0) putchar('-'),x*=-1;
        if (x>=10) write(x/10);
        putchar(x%10+'0');
    }

}

using namespace StandardIO;

namespace Project {

    const int N=505;

    int n,m,tim,top,num;
    int cnt,cnt2;
    int head[N],head2[N];
    struct node {
        int to,next;
    } edge[N<<1],edge2[N<<1];
    int dfn[N],low[N],sta[N],instack[N],belong[N];
    int cost[N],W[N],V[N],G[N][N],d[N],f[N][N],val[N];

    inline void add (int a,int b) {
        edge[++cnt].to=b,edge[cnt].next=head[a],head[a]=cnt;
    }
    inline void add2 (int a,int b) {
        edge2[++cnt2].to=b,edge2[cnt2].next=head2[a],head2[a]=cnt2;
    }
    void tarjan (int now) {
        dfn[now]=low[now]=++tim;
        sta[++top]=now,instack[now]=1;
        for (register int i=head[now]; i; i=edge[i].next) {
            int to=edge[i].to;
            if (!dfn[to]) {
                tarjan(to),low[now]=min(low[now],low[to]);
            } else if (instack[to]) low[now]=min(low[now],dfn[to]);
        }
        if (dfn[now]==low[now]) {
            int v;belong[now]=++num,instack[now]=0;
            while (v=sta[top--],v!=now) {
                belong[v]=num,instack[v]=0;
            }
        }
    }
    void dp (int now) {
        for (register int i=cost[now]; i<=m; ++i) f[now][i]=val[now];
        for (register int e=head2[now]; e; e=edge2[e].next) {
            int to=edge2[e].to;
            dp(to);
            for (register int i=m-cost[now]; i>=0; --i) {
                for (register int j=0; j<=i; ++j) {
                    f[now][i+cost[now]]=max(f[now][i+cost[now]],f[now][i+cost[now]-j]+f[to][j]);
                }
            }
        }
    }

    inline void MAIN () {
        read(n),read(m);
        for (register int i=1; i<=n; ++i) read(W[i]);
        for (register int i=1; i<=n; ++i) read(V[i]);
        for (register int i=1; i<=n; ++i) {
            int x;read(x);
            if (x) add(x,i);
        }
        for (register int i=1; i<=n; ++i) if (!dfn[i]) tarjan(i);
        for (register int i=1; i<=n; ++i) {
            cost[belong[i]]+=W[i],val[belong[i]]+=V[i];
            for (register int e=head[i]; e; e=edge[e].next) {
                int to=edge[e].to;
                if (belong[i]!=belong[to]) G[belong[i]][belong[to]]=1,d[belong[to]]++;
            }
        }
        for (register int i=1; i<=num; ++i) {
            for (register int j=1; j<=num; ++j) {
                if (G[i][j]) add2(i,j);
            }
        }
        for (register int i=1; i<=num; ++i) {
            if (!d[i]) add2(num+1,i);
        }
        dp(num+1);
        printf("%d\n",f[num+1][m]);
    }

}

int main () {
//    freopen(".in","r",stdin);
//    freopen(".out","w",stdout);
    Project::MAIN();
}
posted @ 2019-08-23 19:43  Ilverene  阅读(138)  评论(0编辑  收藏  举报