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

    题目:洛谷P2515、BZOJ2427、codevs1866。

    题目大意:有n个物品,每个物品有重量和价值,且只能选一次。每个物品可能有一个依赖物品,选了该物品必须先选择它的依赖物品(可能会有环)。给出背包的容量,求可以装物品的最大价值。

    解题思路:首先强连通分量缩点,然后树形dp求01背包即可。

    C++ Code:

    #include<bits/stdc++.h>
    int n,m,fa[105],w[105],v[105],dfn[105],low[105],idx=0,ys[105],ltfl=0,dad[105];
    std::vector<int>a[105];
    int f[105][505],W[105],V[105],ans=0,cnt=0,head[105];
    bool instack[105];
    std::stack<int>s;
    inline int debian(){
        int c=getchar();
        for(;!isdigit(c);c=getchar());
        int d=0;
        for(;isdigit(c);c=getchar())
        d=(d<<3)+(d<<1)+(c^'0');
        return d;
    }
    struct edge{
        int to,nxt;
    }e[66667];
    void tarjan(int now){
        dfn[now]=low[now]=++idx;
        s.push(now);
        instack[now]=true;
        if(fa[now]){
            if(dfn[fa[now]]){
                if(instack[fa[now]]&&low[now]>dfn[fa[now]])
                low[now]=dfn[fa[now]];
            }else{
                tarjan(fa[now]);
                if(low[now]>low[fa[now]])low[now]=low[fa[now]];
            }
        }
        if(low[now]==dfn[now]){
            ++ltfl;
            int p;
            do{
                p=s.top();
                s.pop();
                instack[p]=false;
                a[ltfl].push_back(p);
                ys[p]=ltfl;
                W[ltfl]+=w[p];
                V[ltfl]+=v[p];
            }while(p!=now);
        }
    }
    void dp(int now){
        //fprintf(stderr,"233  %d  233
    ",now);
        for(int i=W[now];i<=m;++i)
        f[now][i]=V[now];
        for(int i=head[now];i;i=e[i].nxt){
            dp(e[i].to);
            for(int j=m;j>=W[now];--j){
                for(int k=0;k<=m;++k){
                    if(k+j>m)break;
                    if(f[now][j+k]<f[now][j]+f[e[i].to][k])f[now][j+k]=f[now][j]+f[e[i].to][k];
                }
            }
        }
    }
    int main(){
        n=debian(),m=debian();
        memset(fa,-1,sizeof fa);
        for(int i=1;i<=n;++i)w[i]=debian();
        for(int i=1;i<=n;++i)v[i]=debian();
        for(int i=1;i<=n;++i)fa[i]=debian();
        memset(dfn,0,sizeof dfn);
        memset(W,0,sizeof W);
        memset(V,0,sizeof V);
        for(int i=1;i<=n;++i)
        if(!dfn[i])tarjan(i);
        //fprintf(stderr,"%d
    ",ltfl);
        for(int i=1;i<=n;++i){
            if(fa[i]==0||a[ys[i]].size()>1)dad[ys[i]]=0;else
            dad[ys[i]]=ys[fa[i]];
        }
        memset(f,0,sizeof f);
        memset(head,0,sizeof head);
        //for(int i=1;i<=ltfl;++i)fprintf(stderr,"%d: %d %d %d
    ",i,dad[i],W[i],V[i]);
        for(int i=1;i<=ltfl;++i){
            e[++cnt]=(edge){i,head[dad[i]]};
            head[dad[i]]=cnt;
        }
        dp(0);
        for(int i=0;i<=m;++i)
        if(f[0][i]>ans)ans=f[0][i];
        //for(int i=0;i<=ltfl;++i,putchar('
    '))
        //for(int j=0;j<=m;++j)printf("%d ",f[i][j]);
        return!printf("%d
    ",ans);
    }
  • 相关阅读:
    日志组件logback的介绍及配置使用方法(二)
    日志组件logback的介绍及配置使用方法(一)
    MyBatis+MySQL 返回插入的主键ID
    基于shiro-cas的单点登录、单点登出、统一认证授权系统
    使用Redis存储Nginx+Tomcat负载均衡集群的Session
    数字转大写钱币
    世界四大汽车生产公司
    强制登陆远程桌面
    sql 获取连续年份
    SQL 递归
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/8626260.html
Copyright © 2011-2022 走看看