• BZOJ2427: [HAOI2010]软件安装


    【传送门:BZOJ2427


    简要题意:

      给出n个软件,共有m的空间,每个软件只能安装一次,每个软件安装后占用w[i]的空间,得到v[i]的价值

      有些软件至多有一个它们的父软件,相当于父软件被子软件依赖,只有当父软件被安装,才能安装当前的软件

      求出最大价值


    题解:

      如果x为y的父软件,则x连向y

      很显然会出现多个软件互相依赖的情况,就是成环了

      那么就用强联通缩点,然后将空间和费用累加,作为新点

      然后如果没有父软件的点,设一个虚根0,然后0连向这些点

      设f[i][j]为在i点时使用j的空间的最大价值

      然后在树形DP的时候,在继承的时候保证父节点被选中才能选子节点就可以了


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<cstdlib>
    using namespace std;
    int w[110],v[110];
    struct node
    {
        int x,y,next;
    }a[110],b[110];int len,last[110];
    void ins(int x,int y)
    {
        len++;
        a[len].x=x;a[len].y=y;
        a[len].next=last[x];last[x]=len;
    }
    int dfn[110],low[110],id;
    int belong[110],s;
    int sta[110],tp;
    bool bo[110];
    int V[110],W[110];
    void dfs(int x)
    {
        dfn[x]=low[x]=++id;
        sta[++tp]=x;bo[x]=true;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(dfn[y]==-1)
            {
                dfs(y);
                low[x]=min(low[x],low[y]);
            }
            else
            {
                if(bo[y]==true) low[x]=min(low[x],dfn[y]);
            }
        }
        if(low[x]==dfn[x])
        {
            s++;int i;
            do
            {
                i=sta[tp--];
                belong[i]=s;
                bo[i]=false;
            }while(i!=x);
        }
    }
    int f[110][510];
    int m;
    void treedp(int x)
    {
        f[x][W[x]]=V[x];
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            treedp(y);
            for(int i=m;i>W[x];i--)
            {
                for(int j=0;j<=i-W[x];j++)
                {
                    if(i>=j) f[x][i]=max(f[x][i],f[y][j]+f[x][i-j]);
                }
            }
        }
    }
    int d[110],ru[110];
    int main()
    {int n;
        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]);
        len=0;memset(last,0,sizeof(last));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&d[i]);
            ins(d[i],i);
        }
        memset(bo,false,sizeof(bo));
        id=s=tp=0;
        memset(V,0,sizeof(V));
        memset(W,0,sizeof(W));
        memset(dfn,-1,sizeof(dfn));
        for(int i=1;i<=n;i++) if(dfn[i]==-1) dfs(i);
        len=0;memset(last,0,sizeof(last));
        memset(ru,0,sizeof(ru));
        for(int i=1;i<=n;i++)
        {
            int x=d[i],y=i;
            V[belong[i]]+=v[i];W[belong[i]]+=w[i];
            if(belong[x]!=belong[y])
            {
                ins(belong[x],belong[y]);
                ru[belong[y]]++;
            }
        }
        for(int i=1;i<=s;i++) if(ru[i]==0) ins(0,i);
        treedp(0);
        printf("%d
    ",f[0][m]);
        return 0;
    }
  • 相关阅读:
    括号序列
    NOI剑客决斗
    洛谷 P1896 [SCOI2005]互不侵犯King
    codevs贪吃的九头龙
    ie6绝对定位的块会被select元素遮挡的解决方案
    Normalize.css与Reset CSS:定义浏览器统一的默认样式
    IE6中PNG图片背景无法透明显示的最佳解决方案
    关于ie6中绝对定位或浮动的div中既有向左float也有向右float时候如何让外层div自适应宽度的解决方案--
    [Z]关于html中的条件注释
    [z]IE6各种不兼容问题
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8644580.html
Copyright © 2020-2023  润新知