P4015 运输问题 最小费用最大流

  

题目描述

WW 公司有 mm 个仓库和 nn 个零售商店。第 ii 个仓库有 a_iai 个单位的货物;第 jj 个零售商店需要 b_jbj 个单位的货物。

货物供需平衡,即sumlimits_{i=1}^{m}a_i=sumlimits_{j=1}^{n}b_ji=1mai=j=1nbj

从第 ii 个仓库运送每单位货物到第 jj 个零售商店的费用为 c_{ij}cij​​ 。

试设计一个将仓库中所有货物运送到零售商店的运输方案,使总运输费用最少。

输入输出格式

输入格式:

第 11 行有 22 个正整数 mm 和 nn,分别表示仓库数和零售商店数。

接下来的一行中有 mm 个正整数 a_iai,表示第 ii 个仓库有 a_iai个单位的货物。

再接下来的一行中有 nn 个正整数 b_jbj,表示第 jj 个零售商店需要 b_jbj 个单位的货物。

接下来的 mm 行,每行有 nn 个整数,表示从第 ii 个仓库运送每单位货物到第 jj 个零售商店的费用 c_{ij}cij

输出格式:

两行分别输出最小运输费用和最大运输费用。

输入输出样例

输入样例#1: 复制
2 3
220 280
170 120 210
77 39 105
150 186 122
输出样例#1: 复制
48500
69140

和上一题差不多 不过比上一题麻烦一点

源点给每个仓库连仓库的容量 表示赐予仓库多少货。(一开始练成inf了 答案小了很多)
然后每个商店和汇点连接商店的需求量
中间的话 每个仓库和每个商店连接每个仓库的最大供货量 且加上费用流

#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define inf 0x3f3f3f3f
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
const int N=1000001;

int n,m,S,T,maxflow,mincost,last[N],pre[N],dis[N],flow[N];
bool vis[N];
struct Edge{
    int next,to,flow,dis;
}edge[N<<1];
int pos=1,head[N];
void init()
{
    pos=1;
    CLR(head,0);
    mincost=maxflow=0;
}
queue <int> q;
int id(int x,int y) {return n*(x-1)+y;}

void add(int from,int to,int flow,int dis)
{
    edge[++pos].next=head[from];
    edge[pos].flow=flow;
    edge[pos].dis=dis;
    edge[pos].to=to;
    head[from]=pos;
    edge[++pos].next=head[to];
    edge[pos].flow=0;
    edge[pos].dis=-dis;
    edge[pos].to=from;
    head[to]=pos;
}
bool spfa(int s,int t)
{
    CLR(dis,0x3f);
    CLR(flow,0x3f);
    CLR(vis,0);
    while (!q.empty()) q.pop();
    dis[s]=0; pre[t]=-1; q.push(s); vis[s]=1;
    int tot=0;
    while (!q.empty())
    {
        int now=q.front(); q.pop(); vis[now]=0;
        for (int i=head[now]; i; i=edge[i].next)
        {
            int to=edge[i].to;
            if  (edge[i].flow>0 && dis[to]>dis[now]+edge[i].dis)
            {
                dis[to]=edge[i].dis+dis[now];
                flow[to]=min(edge[i].flow,flow[now]);
                last[to]=i;
                pre[to]=now;
                if (!vis[to])
                {
                    q.push(to); vis[to]=1;
                }
            }
        }
    }
    return pre[t]!=-1;
}
void MCMF(int s,int t)
{
    while (spfa(s,t))
    {
        int now=t;
        maxflow+=flow[t];
        mincost+=flow[t]*dis[t];
        while (now!=s)
        {
            edge[last[now]].flow-=flow[t];
            edge[last[now]^1].flow+=flow[t];
            now=pre[now];
        }
    }
}
struct node
{
    int u,v,cost;
}node[N];
int s,t,k;
int peo[N],thing[N];

int main()
{
    RII(n,m);
    s=0,t=n*m+1;
    rep(i,1,n){ RI(peo[i]);add(s,i,peo[i],0); }
    rep(i,1,m){ RI(thing[i]);add(i+n,t,thing[i],0); }

    int cnt=0;
    rep(i,1,n)
    rep(j,1,m)
    {
        node[++cnt].u=i;node[cnt].v=j;
        RI(node[cnt].cost);
        add(i,j+n,peo[i],node[cnt].cost);
    }

    MCMF(s,t);
    cout<<mincost<<endl;
    init();
    rep(i,1,n)add(s,i,peo[i],0);
    rep(i,1,m)add(i+n,t,thing[i],0);
    rep(i,1,cnt)add(node[i].u,node[i].v+n,peo[node[i].u],-node[i].cost);

    MCMF(s,t);
    cout<<-mincost;
    return 0;
}
View Code


原文地址:https://www.cnblogs.com/bxd123/p/10944219.html