网络流二十四题之十七 —— 运输问题

运输问题


Description

W 公司有 m 个仓库和 n 个零售商店。
i 个仓库有 ai 个单位的货物;第 j 个零售商店需要 bj 个单位的货物。
货物供需平衡,即 mi=1ai=nj=1bj
从第 i 个仓库运送每单位货物到第 j 个零售商店的费用为 cij
试设计一个将仓库中所有货物运送到零售商店的运输方案,使总运输费用最少。
编程任务:
对于给定的 m 个仓库和 n 个零售商店间运送货物的费用,计算最优运输方案和最差运输方案。


Input

1 行有 2 个正整数 m n,分别表示仓库数和零售商店数。
接下来的一行中有 m 个正整数 ai 1im ,表示第 i 个仓库有 ai 个单位的货物。
再接下来的一行中有 n 个正整数 bj 1jn ,表示第 j 个零售商店需要 bj 个单位的货物。
接下来的 m 行,每行有 n 个整数,表示从第 i 个仓库运送每单位货物到第 j 个零售商店的费用 cij


Output

将计算出的最少运输费用和最多运输费用输出。


Sample Input

2 3
220 280
170 120 210
77 39 105
150 186 122


Sample Output

48500
69140


Solution

标准的最小费用流和最大费用流模板题。
感觉网络流越往后做越简单??


Code

[cpp]
  1. #include <iostream>  
  2. #include <cstdio>  
  3. #include <cstring>  
  4. #include <queue>  
  5.   
  6. #define ss 0  
  7. #define tt 100000  
  8. #define INF 0x3f3f3f3f  
  9. #define Min(x,y) ((x)<(y)?(x):(y))  
  10.   
  11. using namespace std;  
  12.   
  13. int cnt,cnt1,ans,m,n,ans0;  
  14. int nxt[100010],head[100010],data[100010];  
  15. int nxt1[100010],head1[100010],data1[100010];  
  16. int flow[100010],wei[100010];  
  17. int flow1[100010],wei1[100010];  
  18. int dis[100010];  
  19. int pre[100010];  
  20. int aa[1000],bb[1000];  
  21. queue<int>q;  
  22. bool in_stack[100010];  
  23.   
  24. void add(int x,int y,int a,int b){    
  25.     nxt[cnt]=head[x];data[cnt]=y;wei[cnt]=-b;flow[cnt]=a;head[x]=cnt++;        
  26.     nxt[cnt]=head[y];data[cnt]=x;wei[cnt]=b;flow[cnt]=0;head[y]=cnt++;     
  27.       
  28.     nxt1[cnt1]=head1[x];data1[cnt1]=y;wei1[cnt1]=b;flow1[cnt1]=a;head1[x]=cnt1++;        
  29.     nxt1[cnt1]=head1[y];data1[cnt1]=x;wei1[cnt1]=-b;flow1[cnt1]=0;head1[y]=cnt1++;  
  30. }    
  31.     
  32. bool BFS(){    
  33.     memset(dis,0x3f,sizeof dis);dis[ss]=0;in_stack[ss]=true;q.push(ss);pre[ss]=pre[tt]=-1;    
  34.     while(!q.empty()){    
  35.         int now=q.front();    
  36.         q.pop();    
  37.         in_stack[now]=false;    
  38.         for(int i=head[now];i!=-1;i=nxt[i]){    
  39.             if(flow[i]!=0&&dis[data[i]]>dis[now]+wei[i]){    
  40.                 dis[data[i]]=dis[now]+wei[i];    
  41.                 pre[data[i]]=i^1;    
  42.                 if(!in_stack[data[i]]){    
  43.                     in_stack[data[i]]=true;    
  44.                     q.push(data[i]);    
  45.                 }    
  46.             }    
  47.         }    
  48.     }    
  49.     return pre[tt]!=-1;    
  50. }    
  51.     
  52. void dfs(){    
  53.     int Low=INF;    
  54.     for(int i=pre[tt];i!=-1;i=pre[data[i]])Low=Min(Low,flow[i^1]);    
  55.     for(int i=pre[tt];i!=-1;i=pre[data[i]])flow[i^1]-=Low,flow[i]+=Low;     
  56.     ans+=Low*dis[tt];    
  57. }  
  58.   
  59. bool BFS1(){    
  60.     memset(dis,0x3f,sizeof dis);dis[ss]=0;in_stack[ss]=true;q.push(ss);pre[ss]=pre[tt]=-1;    
  61.     while(!q.empty()){    
  62.         int now=q.front();    
  63.         q.pop();    
  64.         in_stack[now]=false;    
  65.         for(int i=head1[now];i!=-1;i=nxt1[i]){    
  66.             if(flow1[i]!=0&&dis[data1[i]]>dis[now]+wei1[i]){    
  67.                 dis[data1[i]]=dis[now]+wei1[i];    
  68.                 pre[data1[i]]=i^1;    
  69.                 if(!in_stack[data1[i]]){    
  70.                     in_stack[data1[i]]=true;    
  71.                     q.push(data1[i]);    
  72.                 }    
  73.             }    
  74.         }    
  75.     }    
  76.     return pre[tt]!=-1;    
  77. }    
  78.     
  79. void dfs1(){    
  80.     int Low=INF;    
  81.     for(int i=pre[tt];i!=-1;i=pre[data1[i]])Low=Min(Low,flow1[i^1]);    
  82.     for(int i=pre[tt];i!=-1;i=pre[data1[i]])flow1[i^1]-=Low,flow1[i]+=Low;     
  83.     ans0+=Low*dis[tt];    
  84. }  
  85.   
  86. int main(){  
  87.       
  88.     freopen(”trans.in”,“r”,stdin);  
  89.     freopen(”trans.out”,“w”,stdout);  
  90.   
  91.     memset(head,-1,sizeof head);  
  92.     memset(head1,-1,sizeof head1);  
  93.   
  94.     scanf(”%d%d”,&m,&n);  
  95.       
  96.     for(int i=1;i<=m;i++){  
  97.         int x;  
  98.         scanf(”%d”,&x);  
  99.         aa[i]=x;  
  100.         add(ss,i,x,0);  
  101.     }  
  102.       
  103.     for(int i=1;i<=n;i++){  
  104.         int x;  
  105.         scanf(”%d”,&x);  
  106.         bb[i]=x;  
  107.         add(i+m,tt,x,0);  
  108.     }  
  109.   
  110.     for(int i=1;i<=m;i++)  
  111.         for(int j=1;j<=n;j++){  
  112.             int x;  
  113.             scanf(”%d”,&x);  
  114.             add(i,j+m,Min(aa[i],bb[j]),x);  
  115.         }  
  116.           
  117.       
  118.     while(BFS1())dfs1();  
  119.     while(BFS())dfs();  
  120.       
  121.     printf(”%d\n%d\n”,ans0,-ans);  
  122.     return 0;  
  123. }  
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值