生活随笔
收集整理的這篇文章主要介紹了
poj2516 最小费用最大流
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
第一次見到這樣的題,真的是看別人的思想然后看別人的代碼了一晚上,先明白別人的代碼的意思,但是不懂為什么那么寫,然后畫個圖忽然就明白了,下面就是根據這道題最初最小費用最大流的分析!
題目大意:給出n個客戶對k個商品的需求量,又給出m個倉庫對k個物品的存貨量以及對k個物品從i倉庫到j客戶的一個物品的運費價格,讓判斷是否可以滿足客戶需求,然后就是如果滿足求出最小的運費,是典型的最小費用最大流!
題目解析:可以將k中物品分開求最小然后想加!
建圖,對每個倉庫是一個結點,每個客戶也是一個結點,除此之外再加上s源點和t結束點!
1、s到倉庫i的邊的權值為倉庫i的供給量
2、倉庫i到客戶j的權值為倉庫的供給量
3、客戶j到t的權值為客戶的需求量
4、還有建立花費圖,cost[i][j]代表倉庫i到客戶j的沒一個物品的運費
然后用spfa算法求s到t的最小路徑(路徑上邊的權值不為0),如果到t的最短路徑有更新(此條路徑話費最少),則記錄這條路徑,求出這條路徑上權值最小的邊的權值,然后這條路徑上所有的邊的權值都減去該邊的權值min,此時最小的花費增加了min*在這條邊上的花費!如果s到t的值沒有更新,則對于k物品的最小花費則已經求出來了!
表達能力不強,腦袋清楚說不出來,下面是代碼,如果實在不明白的話就好好看看代碼哈!
?
[html]view plaincopyprint?
#include<iostream>?? #include<cstdio>?? #include<string>?? #include<cmath>?? #include<queue>?? using?namespace?std;?? #define?min(a,b)?(a)<(b)?(a):(b)?? #define?N?130?? #define?inf?100000000?? int?need[N][N];?? int?offer[N][N];?? int?map[N][N],cost[N][N];?? int?sum_need[N],sum_offer[N];?? int?n,m,K;?? int?pre[N];?? int?s,t;//源點和結束點?? int?spfa()?? {?? ????int?dis[N];?? ????bool?vis[N];?? ????int?i;?? ????queue<int>q;?? ????for(i=0;?i<=t;?i++)?? ????{?? ????????vis[i]=false;?? ????????dis[i]=inf;?? ????}?? ????vis[s]=true;?? ????dis[s]=0;?? ????q.push(s);?? ????while(!q.empty())?? ????{?? ????????int?k=q.front();?? ????????vis[k]=false;?? ????????q.pop();?? ????????for(i=0;?i<=t;?i++)?? ????????{?? ?????? ????????????if(map[k][i]?&&?dis[i]>dis[k]+cost[k][i])?? ????????????{?? ????????????????dis[i]=dis[k]+cost[k][i];?? ????????????????pre[i]=k;?? ????????????????if(vis[i]==false)?? ????????????????{?? ????????????????????vis[i]=true;?? ????????????????????q.push(i);?? ????????????????}?? ????????????}?? ????????}?? ????}?? ????if(dis[t]!=inf)?? ????????return?1;?? ????else?? ????????return?0;?? }?? int?fond()?? {?? ????int?i,j;?? ????int?Min=INT_MAX;?? ????j=0;?? ????while(spfa())?? ????{?? ????????for(i=t;i!=s;?i=pre[i])?? ????????????Min=min(Min,map[pre[i]][i]);?? ????????for(i=t;?i!=s;?i=pre[i])?? ????????{?? ????????????map[pre[i]][i]-=Min;?? ????????????map[i][pre[i]]+=Min;?? ????????????j+=cost[pre[i]][i]*Min;?? ????????}?? ????}?? ????return?j;?? }?? int?main()?? {?? ????int?i,j,k,sum,sign;?? ????while(scanf("%d%d%d",&n,&m,&K))?? ????{?? ????????if(n==0?&&?m==0?&&?K==0)?? ????????????break;?? ????????sum=0;?? ????????memset(sum_need,0,sizeof(sum_need));?? ????????memset(sum_offer,0,sizeof(sum_offer));?? ????????for(i=1;?i<=n;?i++)?? ????????????for(j=1;?j<=K;?j++)?? ????????????{?? ????????????????scanf("%d",&need[i][j]);?? ????????????????sum_need[j]+=need[i][j];?? ????????????}?? ?????????for(i=1;?i<=m;?i++)?? ???????????for(j=1;?j<=K;?j++)?? ???????????{?? ???????????????scanf("%d",&offer[i][j]);?? ???????????????sum_offer[j]+=offer[i][j];?? ???????????}?? ????????sign=0;?? ????????for(i=1;?i<=K;?i++)?? ????????????if(sum_offer[i]<sum_need[i])?? ????????????{?? ????????????????sign=1;?? ????????????????break;?? ????????????}??? ????????s=0;?? ????????t=m+n+1;??? ????????for(k=1;?k<=K;?k++)?? ????????{?? ????????????for(i=0;?i<=t;?i++)?? ????????????????for(j=0;?j<=t;?j++)?? ????????????????????map[i][j]=cost[i][j]=0;?? ????????????for(i=1+m;?i<=n+m;?i++)?? ????????????????for(j=1;?j<=m;?j++)?? ????????????????{?? ????????????????????scanf("%d",&cost[j][i]);?? ????????????????????cost[i][j]=-cost[j][i];?? ????????????????}??? ????????????if(sign==1)?? ???????????????continue;???? ????????????for(i=1;?i<=m;?i++)?? ???????????????map[s][i]=offer[i][k];?? ????????????for(i=1;?i<=m;?i++)?? ???????????????for(j=1+m;?j<=n+m;?j++)?? ?????????????????map[i][j]=offer[i][k];???? ???????????for(i=m+1;?i<=m+n;?i++)?? ????????????????map[i][t]=need[i-m][k];?? ??????????sum+=fond();?? ????????}?? ????if(sign==1)?? ????????printf("-1\n");?? ????else?? ????????printf("%d\n",sum);?? ????}?? ?????? ????return?0;?? } ?
總結
以上是生活随笔為你收集整理的poj2516 最小费用最大流的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。