题目描述 Description
W 公司有m个仓库和n 个零售商店。第i 个仓库有ai 个单位的货物;第j 个零售商店
需要bj个单位的货物。货物供需平衡,即 sum(si)=sum(bj)
。从第i 个仓库运送每单位货物到
第j 个零售商店的费用为cij 。试设计一个将仓库中所有货物运送到零售商店的运输方案,
使总运输费用最少。
编程任务:
对于给定的m 个仓库和n 个零售商店间运送货物的费用,计算最优运输方案和最差运输方案。
输入描述 Input Description
的第1行有2 个正整数m和n,分别表示仓库数和
零售商店数。接下来的一行中有m个正整数ai ,1≤i≤m,表示第i个仓库有ai 个单位的货
物。再接下来的一行中有n个正整数bj ,1≤j≤n,表示第j个零售商店需要bj 个单位的货
物。接下来的m行,每行有n个整数,表示从第i 个仓库运送每单位货物到第j个零售商店
的费用cij 。
输出描述 Output Description
将计算出的最少运输费用和最多运输费用输出
样例输入 Sample Input
2 3
220 280
170 120 210
77 39 105
150 186 122
样例输出 Sample Output
48500
69140
题解:最小费用最大流&最大费用最大流
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int n,m,a[1000],maxn,minn,tot;
int next[20000],point[10000],v[20000],remain[200000],remain1[200000];
int cost[20000],cost1[20000],dis[10000],laste[100000],can[10000];
const int inf=1e9;
void add(int x,int y,int z,int k)
{
tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=remain1[tot]=z; cost[tot]=cost1[tot]=k;
tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=remain1[tot]=0; cost[tot]=cost1[tot]=-k;
}
int addflow(int s,int t)
{
int ans=inf;int now=t;
while(now!=s)
{
ans=min(ans,remain[laste[now]]);
now=v[laste[now]^1];
}
now=t;
while(now!=s)
{
remain[laste[now]]-=ans;
remain[laste[now]^1]+=ans;
now=v[laste[now]^1];
}
return ans;
}
int addflow1(int s,int t)
{
int ans=inf;int now=t;
while(now!=s)
{
ans=min(ans,remain1[laste[now]]);
now=v[laste[now]^1];
}
now=t;
while(now!=s)
{
remain1[laste[now]]-=ans;
remain1[laste[now]^1]+=ans;
now=v[laste[now]^1];
}
return ans;
}
bool spfa(int s,int t)
{
memset(dis,128,sizeof(dis));
memset(can,0,sizeof(can));
dis[s]=0; can[s]=1; queue<int> p; p.push(s);
while (!p.empty())
{
int now=p.front(); p.pop();
for (int i=point[now];i!=-1;i=next[i])
if (dis[v[i]]<dis[now]+cost[i]&&remain[i])
{
dis[v[i]]=dis[now]+cost[i];
laste[v[i]]=i;
if (!can[v[i]])
{
can[v[i]]=1;
p.push(v[i]);
}
}
can[now]=0;
}
if (dis[t]<0) return false;
maxn+=addflow(s,t)*dis[t];
return true;
}
bool spfa1(int s,int t)
{
memset(dis,0x7f,sizeof(dis));
memset(can,0,sizeof(can));
dis[s]=0; can[s]=1; queue<int> p; p.push(s);
while (!p.empty())
{
int now=p.front(); p.pop();
for (int i=point[now];i!=-1;i=next[i])
if (dis[v[i]]>dis[now]+cost1[i]&&remain1[i])
{
dis[v[i]]=dis[now]+cost1[i];
laste[v[i]]=i;
if (!can[v[i]])
{
can[v[i]]=1;
p.push(v[i]);
}
}
can[now]=0;
}
if (dis[t]>inf) return false;
minn+=addflow1(s,t)*dis[t];
return true;
}
void maxflow(int s,int t)
{
while(spfa(s,t));
}
void minflow(int s,int t)
{
while(spfa1(s,t));
}
int main()
{
memset(point,-1,sizeof(point));
memset(next,-1,sizeof(next));
tot=-1;
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
int x; scanf("%d",&x);
add(0,i,x,0);
}
for (int i=1;i<=m;i++)
{
int x; scanf("%d",&x);
add(i+n,n+m+1,x,0);
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
int x; scanf("%d",&x);
add(i,j+n,inf,x);
}
maxflow(0,n+m+1);
minflow(0,n+m+1);
printf("%d\n",minn);
printf("%d\n",maxn);
}