[题解] PowerOJ 1752 运输问题 (最大/小费用最大流)
- 传送门 -
https://www.oj.swust.edu.cn/problem/show/1752
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
- 思路 -
同分配问题, 不过也没什么好讲的.
细节见代码.
- 代码 -
#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;
}