给出
m
≤
100
m\leq100
m≤100个仓库和
n
≤
100
n\leq100
n≤100个零售商店,然后每个仓库都用一个供应量,每个零售商店都有一个需求量,而且是供需平衡的。并且告诉你每个仓库到零售商店的运输单位货物的费用。
费用流的模板题,源点连所有的仓库供应量的流量
0
0
0权值,所有零售商店连汇点需求量的流量
0
0
0权值。中间连无限流量和对应的权值。跑费用流。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
namespace MCMF {
const int N=4e3+7,M=1e5+7;
int tot=-1,n,S,T;
int front[N],pre[N],lst[N];
ll flow[N],dis[N];
bool inq[N];
struct edge{ int v,nxt;ll c,w; }e[2*M];
void init() {
tot=-1;
for(int i=1;i<=n;i++) front[i]=-1;
}
void add(int u,int v,ll c,ll w) {
e[++tot].v=v,e[tot].w=w,e[tot].c=c,e[tot].nxt=front[u],front[u]=tot;
e[++tot].v=u,e[tot].w=-w,e[tot].c=0,e[tot].nxt=front[v],front[v]=tot;
}
void reset() {
pre[T]=-1;
for(int i=1;i<=n;i++) dis[i]=flow[i]=1e15;
for(int i=1;i<=n;i++) inq[i]=0;
}
bool spfa() {
reset();
queue<int> q;
q.push(S);
inq[S]=1;dis[S]=0;
while(!q.empty()) {
int u=q.front();
q.pop();
inq[u]=0;
for(int i=front[u];i!=-1;i=e[i].nxt) {
int v=e[i].v;
if(e[i].c>0) {
if(dis[v]>dis[u]+e[i].w) {
dis[v]=dis[u]+e[i].w;
flow[v]=min(flow[u],e[i].c);
pre[v]=u,lst[v]=i;
if(!inq[v]) {
inq[v]=1;
q.push(v);
}
}
}
}
}
return pre[T]!=-1?1:0;
}
pair<ll,ll> solve() {
ll maxflow=0,mincost=0;
while(spfa()) {
int cur=T;
maxflow+=flow[T];
mincost+=flow[T]*dis[T];
while(cur!=S) {
e[lst[cur]].c-=flow[T];
e[lst[cur]^1].c+=flow[T];
cur=pre[cur];
}
}
return make_pair(maxflow,mincost);
}
}
const int N=105;
int a[N],b[N],c[N][N];
int main() {
int m,n;
scanf("%d%d",&m,&n);
for(int i=1;i<=m;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
scanf("%d",&b[i]);
for(int i=1;i<=m;i++) {
for(int j=1;j<=n;j++) {
scanf("%d",&c[i][j]);
}
}
MCMF::n=n+m+2;
int S=n+m+1;
int T=n+m+2;
MCMF::S=n+m+1;
MCMF::T=n+m+2;
MCMF::init();
for(int i=1;i<=m;i++)
MCMF::add(S,i,a[i],0);
for(int i=m+1;i<=n+m;i++)
MCMF::add(i,T,b[i-m],0);
for(int i=1;i<=m;i++) {
for(int j=1;j<=n;j++) {
MCMF::add(i,j+m,1e9,c[i][j]);
}
}
printf("%lld\n",MCMF::solve().second);
MCMF::init();
for(int i=1;i<=m;i++)
MCMF::add(S,i,a[i],0);
for(int i=m+1;i<=m+n;i++)
MCMF::add(i,T,b[i-m],0);
for(int i=1;i<=m;i++) {
for(int j=1;j<=n;j++) {
MCMF::add(i,j+m,1e9,-c[i][j]);
}
}
printf("%lld\n",-MCMF::solve().second);
return 0;
}