W 公司有 m m m 个仓库和 n n n 个零售商店。第 i i i 个仓库有 a i a_i ai 个单位的货物;第 j j j 个零售商店需要 b j b_j bj 个单位的货物。货物供需平衡,即 ∑ i = 1 m a i = ∑ j = 1 n b j \sum\limits_{i = 1} ^ m a_i = \sum\limits_{j = 1} ^ n b_j i=1∑mai=j=1∑nbj。从第 i i i 个仓库运送每单位货物到第 j j j 个零售商店的费用为 c i j c_{ij} cij。试设计一个将仓库中所有货物运送到零售商店的运输方案,使总运输费用最少。
最小费用最大流
普通的最小费用最大流
#include
using namespace std;
const int nmax = 10000;
const int INF = 0x3f3f3f3f;
typedef int valtype;
struct MCMF{
valtype final_flow,final_cost;
int tot,S,T;
bool inque[nmax];
int head[nmax], pre_edge[nmax],pre_index[nmax];
valtype add_flow[nmax], dis[nmax];
struct edge{int to,nxt;valtype cap,flow,cost;}e[nmax<<1];
void init(int S, int T){
memset(head,-1,sizeof head);
tot = 0;
this->S = S, this->T = T;
}
void add_edge(int u, int v, valtype cap, valtype cost){
e[tot].to = v, e[tot].nxt = head[u], e[tot].flow = 0, e[tot].cap = cap, e[tot].cost = cost, head[u] = tot++;
e[tot].to = u, e[tot].nxt = head[v], e[tot].flow = 0, e[tot].cap = 0, e[tot].cost = -cost, head[v] = tot++;
}
bool spfa(){
for(int i = S;i<=T;++i) inque[i] = false, dis[i] = i == S?0:INF;
queue<int> q; q.push(S), inque[S] = true, add_flow[S] = INF;
while(!q.empty()){
int u = q.front(); q.pop(); inque[u] = false;
for(int i = head[u];i!=-1;i=e[i].nxt){
int v = e[i].to;
if(e[i].cap > e[i].flow && dis[u] + e[i].cost < dis[v]){
dis[v] = dis[u] + e[i].cost, pre_edge[v] = i, pre_index[v] = u;
add_flow[v] = min(add_flow[u],e[i].cap - e[i].flow);
if(!inque[v]) q.push(v),inque[v] = true;
}
}
}
return dis[T] != INF;
}
void mincost_mxflow() {
final_cost = final_flow = 0;
while(spfa()){
final_flow += add_flow[T];
final_cost += add_flow[T] * dis[T];
int now = T;
while(now != S){
e[pre_edge[now]].flow += add_flow[T];
e[pre_edge[now]^1].flow -= add_flow[T];
now = pre_index[now];
}
}
}
}mcmf;
int n, m;
int a[105], b[105];
int cost[105][105];
int main() {
scanf("%d %d", &n, &m);
int s = 0, t = n + m + 1, tmp;
mcmf.init(s, t);
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
mcmf.add_edge(s, i, a[i], 0);
}
for(int i = 1; i <= m; ++i) {
scanf("%d", &b[i]);
mcmf.add_edge(n + i, t, b[i], 0);
}
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= m; ++j) {
scanf("%d", &cost[i][j]);
mcmf.add_edge(i, j + n, a[i], cost[i][j]);
}
}
mcmf.mincost_mxflow();
printf("%d\n", mcmf.final_cost);
mcmf.init(s, t);
for(int i = 1; i <= n; ++i)
mcmf.add_edge(s, i, a[i], 0);
for(int i = 1; i <= m; ++i)
mcmf.add_edge(n + i, t, b[i], 0);
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= m; ++j) {
mcmf.add_edge(i, j + n, a[i], -cost[i][j]);
}
}
mcmf.mincost_mxflow();
printf("%d\n", -mcmf.final_cost);
}
zkw最小费用最大流
#include
using namespace std;
const int nmax = 10000;
const int INF = 0x3f3f3f3f;
typedef int valtype;
struct zkwflow {
struct edge {
valtype cost, cap;
int nxt, re, to;
}e[nmax];
int head[nmax], tot, vis[nmax], s, t;
valtype ans, cost, maxflow;
void init(int s, int t) {
memset(head, -1, sizeof(head));
tot = 0;
ans = cost = maxflow = 0;
this->s = s, this->t = t;
}
void add_edge(int u, int v, valtype cap, valtype cost) {
e[tot].to = v;
e[tot].cap = cap;
e[tot].cost = cost;
e[tot].re = tot + 1;
e[tot].nxt = head[u];
head[u] = tot++;
e[tot].to = u;
e[tot].cap = 0;
e[tot].cost = -cost;
e[tot].re = tot - 1;
e[tot].nxt = head[v];
head[v] = tot++;
}
valtype aug(int u, valtype f) {
if(u == t) {
ans += cost * f;
maxflow += f;
return f;
}
// printf("debug %d %d\n", u, f);
vis[u] = 1;
valtype tmp = f;
for(int i = head[u]; i != -1; i = e[i].nxt)
if(e[i].cap && !e[i].cost && !vis[e[i].to]) {
valtype delta = aug(e[i].to, tmp < e[i].cap ? tmp : e[i].cap);
e[i].cap -= delta;
e[e[i].re].cap += delta;
tmp -= delta;
if(!tmp) return f;
}
return f - tmp;
}
bool modlabel(int n) {
valtype delta = INF;
for(int u = 1; u <= n; u++)
if(vis[u])
for(int i = head[u]; i != -1; i = e[i].nxt)
if(e[i].cap && !vis[e[i].to] && e[i].cost < delta) delta = e[i].cost;
if(delta == INF) return false;
for(int u = 1; u <= n; u++)
if(vis[u])
for(int i = head[u]; i != -1; i = e[i].nxt)
e[i].cost -= delta, e[e[i].re].cost += delta;
cost += delta;
return true;
}
valtype costflow() {
do {
do {
memset(vis, 0, sizeof(vis));
}while(aug(s, INF));
}while(modlabel(t));
return ans;
}
}zkw;
int n, m;
int a[105], b[105];
int cost[105][105];
int main() {
scanf("%d %d", &n, &m);
int s = n + m + 1, t = n + m + 2;
zkw.init(s, t);
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
zkw.add_edge(s, i, a[i], 0);
}
for(int i = 1; i <= m; ++i) {
scanf("%d", &b[i]);
zkw.add_edge(n + i, t, b[i], 0);
}
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= m; ++j) {
scanf("%d", &cost[i][j]);
zkw.add_edge(i, j + n, a[i], cost[i][j]);
}
}
zkw.costflow();
printf("%d\n", zkw.ans);
zkw.init(s, t);
for(int i = 1; i <= n; ++i)
zkw.add_edge(s, i, a[i], 0);
for(int i = 1; i <= m; ++i)
zkw.add_edge(n + i, t, b[i], 0);
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= m; ++j) {
zkw.add_edge(i, j + n, a[i], -cost[i][j]);
}
}
zkw.costflow();
printf("%d\n", -zkw.ans);
}