Loj#6011. 运输问题 (最最基础费用流模板题)

来源:互联网 发布:飞利浦 阿里云 编辑:程序博客网 时间:2024/06/10 03:10


题目描述

W 公司有 m mm 个仓库和 n nn 个零售商店。第 i ii 个仓库有 ai a_iai 个单位的货物;第 j jj 个零售商店需要 bj b_jbj 个单位的货物。货物供需平衡,即 ∑i=1mai=∑j=1nbj \sum\limits_{i = 1} ^ m a_i = \sum\limits_{j = 1} ^ n b_ji=1mai=j=1nbj。从第 i ii 个仓库运送每单位货物到第 j jj 个零售商店的费用为 cij c_{ij}cij。试设计一个将仓库中所有货物运送到零售商店的运输方案,使总运输费用最少。

输入格式

第 1 11 行有 2 22 个正整数 m mm 和 n nn,分别表示仓库数和零售商店数。接下来的一行中有 m mm 个正整数 ai a_iai,表示第 i ii 个仓库有 ai a_iai 个单位的货物。再接下来的一行中有 n nn 个正整数 bj b_jbj,表示第 j jj 个零售商店需要 bj b_jbj 个单位的货物。接下来的 m mm 行,每行有 n nn 个整数,表示从第 i ii 个仓库运送每单位货物到第 j jj 个零售商店的费用 cij c_{ij}cij

输出格式

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

样例

样例输入

2 3220 280170 120 21077 39 105150 186 122

样例输出

4850069140

数据范围与提示

1≤n,m≤100 1 \leq n, m \leq 1001n,m100

输出最小费用最大费用, 最大费用就是费用反向建图就好了

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <queue>#include <cmath>#include <vector>using namespace std;const int maxn = 1e2 + 7;const int maxe = 200005;const int INF = 0x3f3f3f3f;int head[maxe], dis[maxn], path[maxn], pre[maxn], book[maxn] , n, m, s, t, k, sum;int a[maxn], b[maxn], c[maxn][maxn];struct node{    int v, w, f, next, cnt;}edge[maxe];void addEdge(int u, int v, int f, int w){    edge[k].v = v;    edge[k].w = w;    edge[k].f = f;    edge[k].cnt = k;    edge[k].next = head[u];    head[u] = k++;    edge[k].v = u;    edge[k].w = -w;    edge[k].f = 0;    edge[k].cnt = k;    edge[k].next = head[v];    head[v] = k++;}void init(){    s = 0, t = n+m+1, k = 0;    memset(head, -1, sizeof(head));}int spfa(){    queue<int> q;    q.push(s);    memset(pre, -1, sizeof(pre));    memset(path, -1, sizeof(path));    for(int i = 1; i <= t; i++) dis[i] = INF;    dis[s] = 0;    memset(book, 0, sizeof(book));    book[s] = 1;    while(!q.empty())    {        int u = q.front();        q.pop();        book[u] = 0;        for(int i = head[u]; i != -1; i = edge[i].next)        {            int to = edge[i].v;            int w = edge[i].w;            int f = edge[i].f;            if(f && dis[to] > dis[u] + w)            {                dis[to] = dis[u] + w;                pre[to] = u;                path[to] = edge[i].cnt;                if(!book[to])                {                    q.push(to);                    book[to] = 1;                }            }        }    }    if(dis[t] != INF) return 1;    else return 0;}int Min_costflow(){    int ans = 0;    int maxflow = 0;    while(spfa())    {        int minx = INF;        for(int i = t; i != s; i = pre[i])        {            minx = min(minx, edge[path[i]].f);        }        maxflow += minx;        ans += dis[t]*minx;        for(int i = t; i != s; i = pre[i])        {            edge[path[i]].f -= minx;            edge[path[i]^1].f += minx;        }    }    return ans;}int main(){    while(~scanf("%d%d", &m, &n))    {        init();        int x, y, z;        for(int i = 1; i <= m; i++)        {            scanf("%d", &a[i]);            addEdge(s, i, a[i], 0);        }        for(int i = 1; i <= n; i++)        {            scanf("%d", &b[i]);            addEdge(i+m, t, b[i], 0);        }        for(int i = 1; i <= m; i++)            for(int j = 1; j <= n; j++)            {                scanf("%d", &c[i][j]);                addEdge(i, j+m, a[i], c[i][j]);            }        printf("%d\n", Min_costflow());        init();        for(int i = 1; i <= m; i++)            addEdge(s, i, a[i], 0);        for(int i = 1; i <= n; i++)            addEdge(i+m, t, b[i], 0);        for(int i = 1; i <= m; i++)            for(int j = 1; j <= n; j++)                addEdge(i, j+m, a[i], -c[i][j]);        printf("%d\n", -Min_costflow());    }    return 0;}




阅读全文
0 0