居民运输问题得到根本改善

6011. 「网络流 24 题」运输问题

题面

这道题巨水无比啊.

人类未来的饮用水就靠这道题供给了.

先来理解下题意.

\(m\)个仓库,第\(i\)个仓库有\(a_i\)个货物.有\(n\)个商店,第\(i\)个商店需要\(b_i\)个货物.从第\(i\)个仓库运到第\(j\)个商店的费用是\(c_{ij}\).

于是网络流的建模就出来了,源点连向仓库,流量为\(a_i\),费用为\(0\).仓库与商店之间相连,流量为\(INF\),费用为\(c_{ij}\),商店与汇点相连,流量为\(b_i\),费用为\(0\).

跑一遍\(MCMF\)求出最小费用.

然后再给费用取反,再跑一遍\(MCMF\)求出最大费用.

代码:


#include "cstdio"
#include "cstring"
#include "algorithm"
#include "iostream"
#include "cmath"
#include "queue"

#define debug(x) printf("debug:%lld\n",x)
#define ll long long
#define INF 2147483647

using namespace std;

struct edge
{
    ll to,next,flow,cost;
}e1[500010],e2[500010];

queue<ll>q1,q2;

ll m,n,start,end,size1,size2,mincost,maxcost;//m个仓库,n个商店.
ll head1[10010],dis1[10010],flow1[10010],last1[10010],pre1[10010];
ll head2[10010],dis2[10010],flow2[10010],last2[10010],pre2[10010];
bool flag1[10010];
bool flag2[10010];

inline void EdgeAdd1(ll,ll,ll,ll);
inline void EdgeAdd2(ll,ll,ll,ll);
inline void MCMF1();
inline void MCMF2();
inline bool SPFA1();
inline bool SPFA2();

signed main(void)
{
    memset(head1,-1,sizeof(head1));
    memset(head2,-1,sizeof(head2));
    scanf("%lld%lld",&m,&n);
    start=0;
    end=m+n+1;
    for(ll _=1;_<=m;_++)
    {
        ll val;
        scanf("%lld",&val);
        EdgeAdd1(start,_,val,0);
        EdgeAdd1(_,start,0,0);
        EdgeAdd2(start,_,val,0);
        EdgeAdd2(_,start,0,0);
    }
    for(ll _=1;_<=n;_++)
    {
        ll val;
        scanf("%lld",&val);
        EdgeAdd1(_+m,end,val,0);
        EdgeAdd1(end,_+m,0,0);
        EdgeAdd2(_+m,end,val,0);
        EdgeAdd2(end,_+m,0,0);
    }
    for(ll _=1;_<=m;_++)
    {
        for(ll __=1;__<=n;__++)
        {
            ll cost;
            scanf("%lld",&cost);
            EdgeAdd1(_,__+m,INF,cost);
            EdgeAdd1(__+m,_,0,-cost);
            EdgeAdd2(_,__+m,INF,-cost);
            EdgeAdd2(__+m,_,0,cost);
        }
    }
    MCMF1();
    MCMF2();
    printf("%lld\n%lld\n",mincost,-maxcost);
return 0;
}

inline void EdgeAdd1(ll from,ll to,ll flow,ll cost)
{
    e1[size1].to=to;
    e1[size1].flow=flow;
    e1[size1].cost=cost;
    e1[size1].next=head1[from];
    head1[from]=size1++;
}

inline void EdgeAdd2(ll from,ll to,ll flow,ll cost)
{
    e2[size2].to=to;
    e2[size2].flow=flow;
    e2[size2].cost=cost;
    e2[size2].next=head2[from];
    head2[from]=size2++;
}

inline void MCMF1()
{
    while(SPFA1())
    {
        ll now=end;
        mincost+=flow1[end]*dis1[end];
        while(now!=start)
        {
            e1[last1[now]].flow-=flow1[end];
            e1[last1[now]^1].flow+=flow1[end];
            now=pre1[now];
        }
    }
}

inline void MCMF2()
{
    while(SPFA2())
    {
        ll now=end;
        maxcost+=flow2[end]*dis2[end];
        while(now!=start)
        {
            e2[last2[now]].flow-=flow2[end];
            e2[last2[now]^1].flow+=flow2[end];
            now=pre2[now];
        }
    }
}

inline bool SPFA1()
{
    memset(dis1,0x3f,sizeof(dis1));
    memset(flag1,false,sizeof(flag1));
    memset(flow1,0x3f,sizeof(flow1));
    q1.push(start);
    pre1[end]=-1;
    dis1[start]=0;
    flag1[start]=true;
    while(q1.empty()==false)
    {
        ll from=q1.front();
        q1.pop();
        flag1[from]=false;
        for(ll _=head1[from];_!=-1;_=e1[_].next)
        {
            ll to=e1[_].to;
            ll cost=e1[_].cost;
            ll flow_=e1[_].flow;
            if(flow_>0&&dis1[to]>dis1[from]+cost)
            {
                dis1[to]=dis1[from]+cost;
                pre1[to]=from;
                last1[to]=_;
                flow1[to]=min(flow1[from],flow_);
                if(flag1[to]==false)
                {
                    q1.push(to);
                    flag1[to]=true;
                }
            }
        }
    }
return pre1[end]==-1?false:true;
}

inline bool SPFA2()
{
    memset(flag2,false,sizeof(flag2));
    memset(dis2,0x3f,sizeof(dis2));
    memset(flow2,0x3f,sizeof(flow2));
    q2.push(start);
    flag2[start]=true;
    dis2[start]=0;
    pre2[end]=-1;
    while(!q2.empty())
    {
        ll from=q2.front();
        q2.pop();
        flag2[from]=false;
        for(ll _=head2[from];_!=-1;_=e2[_].next)
        {
            ll to=e2[_].to;
            ll cost=e2[_].cost;
            ll flow_=e2[_].flow;
            if(flow_>0&&dis2[to]>dis2[from]+cost)
            {
                dis2[to]=dis2[from]+cost;
                pre2[to]=from;
                last2[to]=_;
                flow2[to]=min(flow2[from],flow_);
                if(flag2[to]==false)
                {
                    q2.push(to);
                    flag2[to]=true;
                }
            }
        }
    }
return pre2[end]==-1?false:true;
}

猜你喜欢

转载自www.cnblogs.com/Lemir3/p/11161587.html