poj 2516 Minimum Cost (最小费用流 )

本文介绍了一种利用最小费用最大流算法解决货物运输问题的方法。该问题涉及多个客户、仓库及不同种类的货物,目标是最小化运输总成本。文章通过具体实例展示了算法的实现过程,并提供了一份详细的C语言代码。

题意:有N个客户,M个仓库,和K种货物。已知每个客户需要每种货物的数量,每个仓库存储每种货物的数量,每个仓库运输各种货物去各个客户的单位费用。判断所有的仓库能否满足所有客户的需求,如果可以,求出最少的运输总费用。

 

思路:最小费用最大流。先判断是否每种货物的存储总量都足够,足够的话,对每一种货物进行一次最小费用最大流求出完成这种货物运输的最小总费用,所有的总费用相加就是结果了。

 

 

思路:最小费用最大流。先判断是否每种货物的存储总量都足够,

     足够的话,对每一种货物进行一次最小费用最大  流求出完成这种货物运输的最小总费用,所有的总费用相加就是结果了。

  http://poj.org/problem?id=2516

  1 #include<stdio.h>
  2 #define maxn 200
  3 #define inf 0x7fffffff
  4 #include<string.h>
  5 int  need[maxn][maxn],needk[maxn],have[maxn][maxn],havek[maxn],cap[maxn][maxn],map[maxn][maxn];
  6 int que[maxn],ans,pre[maxn];
  7 int n,m,k,max;
  8 int dis[maxn],vis[maxn];
  9 int min(int x,int y)
 10 {
 11     if(x<y)return x;
 12     else  return y;
 13 }
 14 int SPFA()
 15 {
 16     int i,head=0,tail=0;
 17     for(i=0;i<=max;i++)
 18     {
 19         dis[i]=inf;
 20         vis[i]=0;
 21     }
 22     dis[0]=0;
 23     vis[0]=1;
 24     que[head]=0;
 25     tail++;
 26     while(head!=tail)
 27     {
 28 
 29         int u=que[head];
 30         vis[u]=0;
 31         for(i=0;i<=max;i++)
 32         {
 33             if(cap[u][i]&&dis[i]>dis[u]+map[u][i])
 34             {
 35 
 36                 dis[i]=dis[u]+map[u][i];
 37                 pre[i]=u;
 38                 if(!vis[i])
 39                 {
 40                     vis[i]=1;
 41                     que[tail++]=i;
 42                     if(tail==maxn)tail=0;
 43                 }
 44             }
 45         }
 46         head++;
 47         if(head==maxn)head=0;
 48     }
 49     if(dis[max]==inf)return 0;
 50     else return 1;
 51 }
 52 void Update()
 53 {
 54     int i,sum=inf;
 55     for(i=max;i!=0;i=pre[i])
 56     {
 57         sum=min(sum,cap[pre[i]][i]);//寻找(最短)增广路经上的最小 流量
 58     }
 59 
 60     for(i=max;i!=0;i=pre[i])
 61     {
 62         cap[pre[i]][i]-=sum;
 63         cap[i][pre[i]]+=sum;
 64         ans+=map[pre[i]][i]*sum;
 65 
 66     }
 67 
 68 }
 69 int main()
 70 {
 71     int i,j,l;
 72   while(scanf("%d%d%d",&n,&m,&k)!=EOF)
 73   {
 74       if(n==0&&m==0&&k==0)break;
 75       memset(needk,0,sizeof(needk));
 76       memset(havek,0,sizeof(havek));
 77       for(i=1;i<=n;i++)
 78       {
 79           for(j=1;j<=k;j++)
 80           {
 81               scanf("%d",&need[i][j]);
 82               needk[j]+=need[i][j];
 83           }
 84       }
 85 
 86       for(i=1;i<=m;i++)
 87       {
 88           for(j=1;j<=k;j++)
 89           {
 90               scanf("%d",&have[i][j]);
 91               havek[j]+=have[i][j];
 92           }
 93       }
 94       int f=0;
 95       ans=0;
 96       for(i=1;i<=k;i++)
 97       {
 98           if(needk[i]>havek[i])
 99           {
100               f=1;
101               break;
102           }
103       }
104 
105       max=n+m+1;
106       for(i=1;i<=k;i++)
107       {
108           memset(cap,0,sizeof(cap));
109           for(j=1;j<=n;j++)
110           {
111               for(l=1;l<=m;l++)
112               {
113                   scanf("%d",&map[l][j+m]);
114                   map[j+m][l]=-map[l][j+m];
115                   cap[l][j+m]=inf;
116 
117               }
118           }
119 
120           for(j=1;j<=m;j++)
121           {
122               cap[0][j]=have[j][i];
123               map[0][j]=map[j][0]=0;
124 
125           }
126           for(j=1;j<=n;j++)
127           {
128               cap[j+m][max]=need[j][i];
129               map[j+m][max]=map[max][j+m]=0;
130           }
131 
132           while(SPFA())Update();//最小费用算法
133 
134       }
135       if(!f)printf("%d\n",ans);
136       else printf("-1\n");
137   }
138 }

转载于:https://www.cnblogs.com/acSzz/archive/2012/05/03/2481347.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值