zoukankan      html  css  js  c++  java
  • BZOJ 1061 志愿者招募(最小费用最大流)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1061

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

    思路:

    例如一共需要4天,四天需要的人数依次是4,2,5,3。有5类志愿者,如下表所示:


    设雇佣第i类志愿者的人数为X[i],每个志愿者的费用为V[i],第j天雇佣的人数为P[j],则每天的雇佣人数应满足一个不等式,如上表所述,可以列出

    P[1]=X[1]+X[2]>=4

    P[2]=X[1]+X[3]>=2

    P[3]=X[3]+X[4]+X[5]>=5

    P[4]=X[5]>=3

    对于第i个不等式,添加辅助变量Y[i](Y[i]>=0),可以使其变为等式

    P[1]=X[1]+X[2]-Y[1]=4

    P[2]=X[1]+X[3]-Y[2]=2

    P[3]=X[3]+X[4]+X[5]-Y[3]=5

    P[4]=X[5]-Y[4]=3

    在上述四个等式上下添加P[0]=0,P[5]=0,每次用下边的式子减去上边的式子,得出

    ① P[1]-P[0]=X[1]+X[2]-Y[1]=4

    ② P[2]-P[1]=X[3]-X[2]-Y[2]+Y[1]=-2

    ③ P[3]-P[2]=X[4]+X[5]-X[1]-Y[3]+Y[2]=3

    ④ P[4]-P[3]=-X[3]-X[4]+Y[3]-Y[4]=-2

    ⑤ P[5]-P[4]=-X[5]+Y[4]=-3

    观察发现,每个变量都在两个式子中出现了,而且一次为正,一次为负.所有等式右边和为0.我们将最后的五个等式进一步变形,得出以下结果

    ① -X[1]-X[2]+Y[1]+4=0

    ② -X[3]+X[2]+Y[2]-Y[1]-2=0

    ③ -X[4]-X[5]+X[1]+Y[3]-Y[2]+3=0

    ④ X[3]+X[4]-Y[3]+Y[4]-2=0

    ⑤ X[5]-Y[4]-3=0

    可 以发现,每个等式左边都是几个变量和一个常数相加减,右边都为0,恰好就像网络流中除了源点和汇点的顶点都满足流量平衡。每个正的变量相当于流入该顶点的 流量,负的变量相当于流出该顶点的流量,而正常数可以看作来自附加源点的流量,负的常数是流向附加汇点的流量。因此可以据此构造网络,求出从附加源到附加 汇的网络最大流,即可满足所有等式。而我们还要求费用最小,所以要在X变量相对应的边上加上权值,然后求最小费用最大流

    接下来,根据上面五个等式构图。

    (1)每个等式为图中一个顶点,添加源点S和汇点T。

    (2)如果一个等式中的数字为非负整数c,从源点S向该等式对应的顶点连接一条容量为c,权值为0的有向边;如果为负整数-c,从该等式对应的顶点向汇点T连接一条容量为c,权值为0的有向边。

    (3)如果一个变量X[i]在第j个等式中出现为-X[i],在第k个等式中出现为+X[i],从顶点j向顶点k连接一条容量为INF,权值为V[i]的有向边。

    (4)如果一个变量Y[i]在第j个等式中出现为-Y[i],在第k个等式中出现为+Y[i],从顶点j向顶点k连接一条容量为INF,权值为0的有向边。

    构图以后,求从源点S到汇点T的最小费用最大流,费用值就是结果。

    struct node
    {
        int cost,flow,v,u,next;
    };
    
    
    node edges[N*1000];
    int head[N],e,s,t;
    int pre[N];
    
    
    void add(int u,int v,int flow,int cost)
    {
        edges[e].u=u;
        edges[e].v=v;
        edges[e].cost=cost;
        edges[e].flow=flow;
        edges[e].next=head[u];
        head[u]=e++;
    }
    
    
    void Add(int u,int v,int flow,int cost)
    {
        add(u,v,flow,cost);
        add(v,u,0,-cost);
    }
    
    
    int SPFA(int s,int t)
    {
        clr(pre,-1);
        int F[N],h[N],C[N],i,u,v,f,c;
        queue<int> Q;
        FOR0(i,t+1) C[i]=INF,h[i]=0,F[i]=0;
        Q.push(s); C[s]=0; F[s]=INF;
        while(!Q.empty())
        {
            u=Q.front();
            Q.pop();
    
    
            h[u]=0;
            for(i=head[u];i!=-1;i=edges[i].next)
            {
                v=edges[i].v;
                f=edges[i].flow;
                c=edges[i].cost;
                if(f>0&&C[v]>C[u]+c)
                {
                    C[v]=C[u]+c;
                    F[v]=min(F[u],f);
                    pre[v]=i;
                    if(!h[v]) h[v]=1,Q.push(v);
                }
            }
        }
        return F[t];
    }
    
    
    int MCMF(int s,int t)
    {
        int ans=0,i,temp;
        while(temp=SPFA(s,t))
        {
            for(i=pre[t];i!=-1;i=pre[edges[i].u])
            {
                ans+=temp*edges[i].cost;
                edges[i].flow-=temp;
                edges[i^1].flow+=temp;
            }
        }
        return ans;
    }
    
    
    int n,m,d[N];
    
    
    int main()
    {
        RD(n,m); clr(head,-1); e=0; s=0; t=n+2;
        int i,u,v,c,temp;
        FOR1(i,n) RD(d[i]);
        FOR1(i,m)
        {
            RD(u,v,c);
            Add(u,v+1,INF,c);
        }
        FOR1(i,n+1)
        {
            temp=d[i]-d[i-1];
            if(temp>=0) Add(s,i,temp,0);
            else Add(i,t,-temp,0);
            if(i>1) Add(i,i-1,INF,0);
        }
        PR(MCMF(s,t));
    }
    
  • 相关阅读:
    JMeter参数签名——Groovy工具类形式
    arthas进阶thread命令视频演示
    疫情期间,如何提高远程办公效率
    Groovy中的闭包
    arthas快速入门视频演示
    绑定手机号性能测试
    基于HTTP请求的多线程实现类--视频讲解
    合格的测试经理必备技能
    Error Code : 1064 You have an error in your SQL syntax; check the manual that corresponds to your My
    Navicat Premium怎么设置字段的唯一性(UNIQUE)?
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/3799759.html
Copyright © 2011-2022 走看看