[题解] PowerOJ 1752 运输问题 (最大/小费用最大流)

- 传送门 -

 https://www.oj.swust.edu.cn/problem/show/1752

# 1752: 运输问题 Time Limit: 1000 MS Memory Limit: 65536 KB Total Submit: [58](https://www.oj.swust.edu.cn/status?pid=1752) Accepted: [49](https://www.oj.swust.edu.cn/status?pid=1752&result=0) Page View: 404

Description

W 公司有m个仓库和n 个零售商店。第i 个仓库有ai 个单位的货物;第j 个零售商店 需要bj个单位的货物。货物供需平衡,即sum(ai)=sum(bj) 。从第i 个仓库运送每单位货物到 第j 个零售商店的费用为Cij 。试设计一个将仓库中所有货物运送到零售商店的运输方案, 使总运输费用最少。 编程任务: 对于给定的m 个仓库和n 个零售商店间运送货物的费用,计算最优运输方案和最差运 输方案。

Input

由文件input.txt提供输入数据。文件的第1行有2 个正整数m和n,分别表示仓库数和 零售商店数。接下来的一行中有m个正整数ai ,1≤i≤m,表示第i个仓库有ai 个单位的货 物。再接下来的一行中有n个正整数bj ,1≤j≤n,表示第j个零售商店需要bj 个单位的货 物。接下来的m行,每行有n个整数,表示从第i 个仓库运送每单位货物到第j个零售商店 的费用Cij 。

Output

程序运行结束时,将计算出的最少运输费用和最多运输费用输出到文件output.txt中。

2 3
220 280
170 120 210
77 39 105
150 186 122

48500
69140

Source

线性规划与网络流24题
 

- 思路 -

 同分配问题, 不过也没什么好讲的.
 
 细节见代码.
 

- 代码 -

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
 
const int N = 200;
const int M = 2e3 + 5;
const int inf = 0x3f3f3f3f;
 
int TO[M], V[M], SP[M], NXT[M], CT[M];
int HD[N], DIS[N], VIS[N], PRE[N];
int ss, tt, sz, n, m;
queue<int> q;
 
void add(int x, int y, int z, int c) {
    TO[sz] = y; V[sz] = z; CT[sz] = c;
    SP[sz] = z; NXT[sz] = HD[x]; HD[x] = sz++;
    TO[sz] = x; V[sz] = 0; CT[sz] = -c;
    SP[sz] = 0; NXT[sz] = HD[y]; HD[y] = sz++;
}
 
bool max_spfa() {
    memset(DIS, 0xc0, sizeof (DIS));
    DIS[ss] = 0;
    q.push(ss);
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        VIS[u] = 0;
        for (int i = HD[u]; i != -1; i = NXT[i]) {
            int v = TO[i];
            if (V[i] && DIS[v] < DIS[u] + CT[i]) {
                DIS[v] = DIS[u] + CT[i];
                PRE[v] = i;
                if (!VIS[v]) {
                    VIS[v] = 1;
                    q.push(v);
                }
            }
        }
    }
    return DIS[tt] > 0;
}
 
bool min_spfa() {
    memset(DIS, 0x3f, sizeof (DIS));
    DIS[ss] = 0;
    q.push(ss);
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        VIS[u] = 0;
        for (int i = HD[u]; i != -1; i = NXT[i]) {
            int v = TO[i];
            if (V[i] && DIS[v] > DIS[u] + CT[i]) {
                DIS[v] = DIS[u] + CT[i];
                PRE[v] = i;
                if (!VIS[v]) {
                    VIS[v] = 1;
                    q.push(v);
                }
            }
        }
    }
    return DIS[tt] < inf;
}
 
void mcmf(int &c) {
    int tmp = inf;
    for (int i = tt; i != ss; i = TO[PRE[i]^1])
        if (tmp > V[PRE[i]]) tmp = V[PRE[i]];
    for (int i = tt; i != ss; i = TO[PRE[i]^1]) {
        V[PRE[i]] -= tmp;
        V[PRE[i]^1] += tmp;
    }
    c += tmp * DIS[tt]; 
}
 
int macmf() {
    int cost = 0;
    while (max_spfa())
        mcmf(cost);
    return cost;
}
 
int micmf() {
    int cost = 0;
    while (min_spfa()) {
        mcmf(cost);
    }
    return cost;
}
 
int main() {
    memset(HD, -1, sizeof (HD));
    scanf("%d%d", &n, &m);
    ss = 0, tt = n + m + 1;
    for (int i = 1, x; i <= n; ++i) {
        scanf("%d", &x);
        add(ss, i, x, 0);
    }
    for (int i = 1, x; i <= m; ++i) {
        scanf("%d", &x);
        add(i + n, tt, x, 0);
    }
    for (int i = 1, x; i <= n; ++i)
        for (int j = 1; j <= m; ++j) {
            scanf("%d", &x);
            add(i, n + j, inf, x);
        }
    printf("%d\n", micmf());
    for (int i = 0; i < sz; ++i)
        V[i] = SP[i];
    printf("%d\n", macmf());
    return 0;
}
posted @ 2017-08-24 21:46  lstttt  阅读(181)  评论(0编辑  收藏  举报