zoukankan      html  css  js  c++  java
  • 【BZOJ2427】[HAOI2010] 软件安装(缩点+树形DP)

    点此看题面

    大致题意:(N)个软件,每个软件有至多一个依赖以及一个所占空间大小(W_i),只有当一个软件的直接依赖和所有的间接依赖都安装了,它才能正常工作并造成(V_i)的价值。求在容量为(M)时的最大价值和。

    大致思路

    比较显然是树上背包

    但是,这题中可能会出现,因此我们要先用(Tarjan)来缩点。

    还要注意,缩完点后的图是一个森林,因此我们需要再人为建一个根,将其向每棵树的根连一条边,这样就可以直接树形(DP)了。

    主要是注意细节啊。

    代码

    #include<bits/stdc++.h>
    #define max(x,y) ((x)>(y)?(x):(y))
    #define min(x,y) ((x)<(y)?(x):(y))
    #define Gmax(x,y) (x<(y)&&(x=(y)))
    #define Gmin(x,y) (x>(y)&&(x=(y))) 
    #define abs(x) ((x)<0?-(x):(x))
    #define swap(x,y) (x^=y^=x^=y)
    #define uint unsigned int
    #define LL long long
    #define ull unsigned long long
    #define INF 1000000000
    #define N 100
    #define M 500 
    #define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
    using namespace std;
    int n,m,ee,fa[N+5],w[N+5],v[N+5],lnk[N+5],deg[N+5];
    struct edge
    {
        int to,nxt;
    }e[N+5];
    class Class_FIO
    {
        private:
            #define Fsize 100000
            #define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,Fsize,stdin),A==B)?EOF:*A++)
            #define pc(ch) (void)(FoutSize<Fsize?Fout[FoutSize++]=ch:(fwrite(Fout,1,FoutSize,stdout),Fout[(FoutSize=0)++]=ch))
            int f,FoutSize,Top;char ch,Fin[Fsize],*A,*B,Fout[Fsize],Stack[Fsize];
        public:
            Class_FIO() {A=B=Fin;}
            inline void read(int &x) {x=0,f=1;while(!isdigit(ch=tc())) f=ch^'-'?1:-1;while(x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));x*=f;}
            inline void write(int x) {if(!x) return pc('0');x<0&&(pc('-'),x=-x);while(x) Stack[++Top]=x%10+48,x/=10;while(Top) pc(Stack[Top--]);}
            inline void clear() {fwrite(Fout,1,FoutSize,stdout),FoutSize=0;}
    }F;
    class Class_Tarjan//Tarjan缩点
    {
        private:
            int d,Top,dfn[N+5],low[N+5],Stack[N+5],InStack[N+5];
        public:
            int cnt,col[N+5],Weight[N+5],Val[N+5];
            inline bool Vis(int x) {return dfn[x];}
            inline void Solve(int x,int lst=0)
            {
                register int i;
                for(dfn[x]=low[x]=++d,InStack[Stack[++Top]=x]=1,i=lnk[x];i;i=e[i].nxt)
                {
                    if(!dfn[e[i].to]) Solve(e[i].to,x),Gmin(low[x],low[e[i].to]);
                    else if(InStack[e[i].to]) Gmin(low[x],dfn[e[i].to]);
                }
                if(dfn[x]^low[x]) return;
                Weight[col[x]=++cnt]=w[x],Val[cnt]=v[x],InStack[x]=0;
                while(Stack[Top]^x) Weight[col[Stack[Top]]=cnt]+=w[Stack[Top]],Val[cnt]+=v[Stack[Top]],InStack[Stack[Top--]]=0;
                --Top;
            }
            inline void ReBuild()//重新建图
            {
                register int i;
                for(ee=0,i=1;i<=n;++i) lnk[i]=0;//清空原先的边
                for(i=1;i<=n;++i) col[fa[i]]^col[i]&&(add(col[fa[i]],col[i]),++deg[col[i]]);//建新边
                for(i=1;i<=cnt;++i) !deg[i]&&add(0,i);//将0号节点向每棵树的根连一条边
            }
    }T;
    class Class_TreeDP//树形DP求解树上背包
    {
        private:
            int f[N+5][M+5],g[N+5];
            inline void DP(int x)
            {
                register int i,j,k,lim;
                for(i=g[x]=T.Weight[x];i<=m;++i) f[x][i]=T.Val[x];
                for(i=lnk[x];i;i=e[i].nxt) for(DP(e[i].to),g[x]+=g[e[i].to],j=min(m,g[x]);j>=T.Weight[x];--j)
                    for(k=1,lim=min(j-T.Weight[x],g[e[i].to]);k<=lim;++k) Gmax(f[x][j],f[x][j-k]+f[e[i].to][k]);
            }
        public:
            inline void Solve()	{DP(0),F.write(f[0][m]);}
    }TreeDP;
    int main()
    {
        register int i;
        for(F.read(n),F.read(m),i=1;i<=n;++i) F.read(w[i]);
        for(i=1;i<=n;++i) F.read(v[i]);
        for(i=1;i<=n;++i) F.read(fa[i]),fa[i]&&add(fa[i],i);
        for(i=1;i<=n;++i) if(!T.Vis(i)) T.Solve(i);
        return T.ReBuild(),TreeDP.Solve(),F.clear(),0;
    }
    
  • 相关阅读:
    ok6410驱动usb摄像头
    自己动手写CPU之第五阶段(1)——流水线数据相关问题
    ListView嵌套ListView时发生:View too large to fit into drawing cache的问题
    算法导论 第8章 线性时间排序(计数排序、基数排序、桶排序)
    Android_通过ContentObserver监听短信数据变化
    【MyEcplise】导入项目报错:Errors running builder 'JavaScript Validator' on project '项目名'. java.lang.ClassCastException
    【js】js中const,var,let区别
    【Node.js】2.开发Node.js选择哪个IDE 开发工具呢
    【Node.js】1.安装步骤
    【POI】对于POI无法处理超大xls等文件,官方解决方法【已解决】【多线程提升速率待定】
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ2427.html
Copyright © 2011-2022 走看看