[网络流24题]code vs 1914 运输问题

1914 运输问题

 时间限制: 2 s
 空间限制: 256000 KB
 题目等级 : 大师 Master
题目描述 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);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值