• bzoj1061 NOI2018 志愿者招募——solution


    Description

      申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管。布布刚上任就遇到了一个难
    题:为即将启动的奥运新项目招募一批短期志愿者。经过估算,这个项目需要N 天才能完成,其中第i 天至少需要
    Ai 个人。 布布通过了解得知,一共有M 类志愿者可以招募。其中第i 类可以从第Si 天工作到第Ti 天,招募费用
    是每人Ci 元。新官上任三把火,为了出色地完成自己的工作,布布希望用尽量少的费用招募足够的志愿者,但这
    并不是他的特长!于是布布找到了你,希望你帮他设计一种最优的招募方案。

    Input

      第一行包含两个整数N, M,表示完成项目的天数和可以招募的志愿者的种类。 接下来的一行中包含N 个非负
    整数,表示每天至少需要的志愿者人数。 接下来的M 行中每行包含三个整数Si, Ti, Ci,含义如上文所述。为了
    方便起见,我们可以认为每类志愿者的数量都是无限多的。

    Output

      仅包含一个整数,表示你所设计的最优方案的总费用。

            -bybzoj

    http://www.lydsy.com/JudgeOnline/problem.php?id=1061



    介绍一种简单的有上下界费用流解法:
    把每个志愿者看做1流量,
    首先把n天按从1到n的顺序顺次连INF的边,任何刑期未满的志愿者都可以在这个边上流动;
    由于每天有一个人数下限,于是考虑,拆点,在代表同一天的两点见连一条有下界的边,
    如何把志愿者引入这个图?
    考虑每个志愿者依照自己所属的种类,将在固定的点进入图,固定的点离开图,并在这两点间流动,
    于是若类型i的志愿者从ai入,bi出,
    则若只有i的话,ai有多少流量被引入,bi就有多少流量消失,不妨连一条费用1流量INF的边从bi到ai
    至此网络流图模型便建好了
    在此图上跑有上下界的最小费用流即可;
    代码:
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int INF=0x3f3f3f3f;
    int n,m,S,T,ansf,answ;
    struct ss{
        int next,to,f,v,cp;
    }e[28010];
    int first[2010],num;
    int que[100010],vis[2010],flow[2010],way[2010],dis[2010],pre[2010];
    void bui_(int ,int ,int ,int );
    void build(int ,int ,int ,int );
    bool spfa();
    void EK();
    int main(){
        int i,j,k,l;
        scanf("%d%d",&n,&m);
        S=(n<<1)+1,T=S+1;
        for(i=1;i<=n;i++){
            bui_(i,i+n,INF,0);
            scanf("%d",&j);
            if(j)bui_(S,i+n,j,0),bui_(i,T,j,0);
            if(i!=n)
                bui_(i+n,i+1,INF,0);
        }
        for(i=1;i<=m;i++){
            scanf("%d%d%d",&j,&k,&l);
            bui_(k+n,j,INF,l);
        }
        while(spfa())
            EK();
        printf("%d
    ",ansf);
    }
    void bui_(int f,int t,int fi,int vi){
        build(f,t,fi,vi),e[num].cp=num+1;
        build(t,f,0,-vi),e[num].cp=num-1;
    }
    void build(int f,int t,int fi,int vi){
        e[++num].next=first[f];
        e[num].to=t,e[num].f=fi,e[num].v=vi;
        first[f]=num;
    }
    bool spfa(){
        int i,h=0,t=1;
        memset(dis,0x3f,sizeof(dis));
        que[t]=S,vis[S]=1,dis[S]=0,flow[S]=INF;
        while(h<t){
            vis[que[++h]]=0;
            for(i=first[que[h]];i;i=e[i].next)
                if(e[i].f&&dis[e[i].to]>dis[que[h]]+e[i].v){
                    dis[e[i].to]=dis[que[h]]+e[i].v;
                    way[e[i].to]=i,pre[e[i].to]=que[h];
                    flow[e[i].to]=min(flow[que[h]],e[i].f);
                    if(!vis[e[i].to]){
                        que[++t]=e[i].to;
                        vis[que[t]]=1;
                    }
                }
        }
        return dis[T]!=INF;
    }
    void EK(){
        int i;
        ansf+=flow[T]*dis[T];
        answ+=flow[T];
        for(i=T;i;i=pre[i])
            if(way[i])
                e[way[i]].f-=flow[T],e[e[way[i]].cp].f+=flow[T];
    }
  • 相关阅读:
    9、 docker容器数据卷
    第十八章 MySQL数据库优化
    第十七章 MySQL的VIP漂移和Atlas
    第十六章 MHA高可用(续)
    第一章 shell基础
    第十五章 MHA高可用
    第十四章 MySQL的各种主从
    第十三章 MySQL的主从复制
    第十二章 MySQL的恢复与备份
    第十一章 MySQL日志详解
  • 原文地址:https://www.cnblogs.com/nietzsche-oier/p/8205275.html
Copyright © 2020-2023  润新知