最小費用最大流


網絡流的費用: 在實際應用中,與網絡流有關的問題,不僅涉及流量,而且還有費用的因素。網絡的每一條邊(v,w)除了給定容量cap(v,w)外,還定義了一個單位流量費用cost(v,w)。對於網絡中一個給定的流flow,其費用定義為:

網絡流定義.jpg 


最小費用最大流問題 給定網絡G,要求G的一個最大用流flow,使流的總費用最小。

求解MCMF問題的算法: 在這里各種算法的證明以及原理的詳解不再贅述,僅僅介紹算法的過程。相關內容感興趣的同學可以自己去搜索資料。 最小費用最大流最常用和基本的算法我們可以稱它為最小費用路算法,其思想與求最大流的增廣路算法類似,不斷在殘流網絡中尋找從源s到匯t的最小費用路,即殘流網絡中從s到t的以費用為權的最短路,然后沿最小費用路增流,直至找到最小費用流。 殘流網絡中邊的費用定義為:

MCMF.jpg 


當殘流網絡中邊(v,w)是向前邊時,其費用為cost(v,w); 當(v,w)是向后邊時,其費用為-cost(w,v)。

最小費用流的最小費用路算法

步驟0:初始可行0流。  步驟1:如果不存在最小費用路,則計算結束,已經找到最小費用流;否則用最短路算法在殘流網絡中找從s到t的最小費用可增廣路,轉步驟2。  步驟2:沿找到的最小費用可增廣路增流,並轉步驟1。 

最小費用路算法的復雜度主要依靠於求最短路的方法,由於負權的存在,不會選擇dijstra等算法,一般bellman-ford,spfa等用來解決費用流的最短路問題。

 

 

模版題:

POJ 2135

代碼: 

 

View Code 
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <queue>
  5  using  namespace std;
  6  int sumFlow;
  7  const  int MAXN =  1010;
  8  const  int MAXM =  1000200;
  9  const  int INF =  1000000000;
 10  struct Edge
 11 {
 12      int u;
 13      int v;
 14      int cap;
 15      int cost;
 16      int next;
 17 }edge[MAXM<< 2];
 18  int NE;
 19  int head[MAXN], dist[MAXN], pp[MAXN];
 20  bool vis[MAXN];
 21  void init()
 22 {
 23     NE= 0;
 24     memset(head,- 1, sizeof(head));
 25 }
 26  void addedge( int u, int v, int cap, int cost)
 27 {
 28     edge[NE].u=u;edge[NE].v=v;edge[NE].cap=cap;edge[NE].cost=cost;
 29     edge[NE].next=head[u];head[u]=NE++;
 30     edge[NE].u=v;edge[NE].v=u;edge[NE].cap= 0;edge[NE].cost=-cost;
 31     edge[NE].next=head[v];head[v]=NE++;
 32 }
 33  bool SPFA( int s, int t, int n)
 34 {
 35      int i,u,v;
 36     queue< int>qu;
 37     memset(vis, false, sizeof(vis));
 38     memset(pp,- 1, sizeof(pp));
 39      for(i= 0;i<=n;i++) 
 40         dist[i]=INF;
 41     vis[s]= true;
 42     dist[s]= 0;
 43     qu.push(s);
 44      while(!qu.empty())
 45     {
 46         u=qu.front();
 47         qu.pop();
 48         vis[u]= false;
 49          for(i=head[u];i!=- 1;i=edge[i].next)
 50         {
 51             v=edge[i].v;
 52              if(edge[i].cap&&dist[v]>dist[u]+edge[i].cost)
 53             {
 54                 dist[v]=dist[u]+edge[i].cost;
 55                 pp[v]=i;
 56                  if(!vis[v])
 57                 {
 58                     qu.push(v);
 59                     vis[v]= true;
 60                 }
 61             }
 62         }
 63     }
 64      if(dist[t]==INF) 
 65          return  false;
 66      return  true;
 67 }
 68  int MCMF( int s, int t, int n)
 69 {
 70      int flow= 0//  總流量
 71       int i,minflow,mincost;
 72     mincost= 0;
 73      while(SPFA(s,t,n))
 74     {
 75         minflow=INF+ 1;
 76          for(i=pp[t];i!=- 1;i=pp[edge[i].u])
 77              if(edge[i].cap<minflow)
 78                 minflow=edge[i].cap;
 79         flow+=minflow;
 80          for(i=pp[t];i!=- 1;i=pp[edge[i].u])
 81         {
 82             edge[i].cap-=minflow;
 83             edge[i^ 1].cap+=minflow;
 84         }
 85         mincost+=dist[t]*minflow;
 86     }
 87     sumFlow=flow;  //  最大流
 88       return mincost;
 89 }
 90  int main()
 91 {
 92      int n,m;
 93      int u,v,c;
 94      while(~scanf( " %d%d ",&n,&m))
 95     {
 96         init();
 97          int S= 0;
 98          int T=n+ 1;
 99          while(m--)
100         {
101             scanf( " %d%d%d ",&u,&v,&c);
102             addedge(u,v, 1,c);
103             addedge(v,u, 1,c);
104         }
105         addedge(S, 1, 2, 0);
106         addedge(n,T, 2, 0);
107          int ans=MCMF(S,T,T+ 1);
108         printf( " %d\n ",ans);
109     }
110      return  0;
111 }
112

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM