最小费用最大流问题及ADT

在总流量最大的前提下,总费用最小的流为最小费用最大流。

分别用$c$和$a$表示每条边的容量和费用。

和最大流问题的区别要注意的是:可能存在平行边,它们的费用不同,所以无法合并这两条弧。(先假设图存在平行边和反向边),这样就可以用邻接矩阵cap和cost来保存各边的容量和费用了。

最小费用路算法和EK算法类似,但是每次用Bellman-Ford算法来找增广路。只要初始流是该流量下的最小费用可行流,每次增广后的新流都是新流量下的最小费用流。

cost最好用longlong保存减小溢出可能

ADT:

 1 #include <iostream>
 2 #include <vector>
 3 #include <queue>
 4 using namespace std;
 5 
 6 const int INF = 1000000000;
 7 const int maxn = 1000;
 8 
 9 struct Edge{
10     int from, to, cap, flow, cost;
11     Edge(int u, int v, int c, int f, int w):from(u), to(v), cap(c), flow(f), cost(w){}
12 };
13 
14 struct MCMF{
15     int n,m;
16     vector<Edge> edges;
17     vector<int> G[maxn];
18     int inq[maxn]; //是否在队列中
19     int d[maxn]; //Bellman-Ford
20     int p[maxn]; //上一条弧
21     int a[maxn]; //可改进量
22     
23     void init(int n){
24         this->n = n;
25         for(int i=0;i<n;i++){
26             G[i].clear();
27         }
28         edges.clear();
29     }
30     
31     void AddEdge(int from, int to, int cap, int cost){
32         edges.push_back(Edge(from,to,cap,0,cost));
33         edges.push_back(Edge(to,from,0,0,-cost));
34         m = edges.size();
35         G[from].push_back(m-2);
36         G[to].push_back(m-1);
37     }
38     
39     bool BellmanFord(int s, int t, int& flow, long long& cost){
40         for(int i=0;i<n;i++){
41             d[i] = INF;
42         }
43         memset(inq, 0, sizeof(inq));
44         d[s] = 0;
45         inq[s] = 1;
46         p[s] = 0;
47         a[s] = INF;
48         
49         queue<int> Q;
50         Q.push(s);
51         while(!Q.empty()){
52             int u = Q.front();
53             Q.pop();
54             inq[u] = 0;//出队
55             for(int i =0;i<G[u].size();i++){
56                 Edge& e=edges[G[u][i]]; //用e(带地址符)来代替后面一长串是很方便的写法,表示这条边
57                 if(e.cap>e.flow&&d[e.to]>d[u]+e.cost){
58                     d[e.to] = d[u]+e.cost;
59                     p[e.to] = G[u][i];
60                     a[e.to] = min(a[u],e.cap-e.flow);
61                     if(!inq[e.to]){
62                         Q.push(e.to);
63                         inq[e.to] = 1;
64                     }
65                 }
66             }
67         }
68         if(d[t]==INF){
69             return false;
70         }
71         flow += a[t];
72         cost += (long long)d[t]*(long long)a[t];
73         for(int u=t;u!=s;u=edges[p[u]].from){
74             edges[p[u]].flow += a[t];
75             edges[p[u]^1].flow -= a[t]; //反向边(在edge中两条边相邻)
76         }
77         return true;
78     }
79     
80     //需要保证初始网络中没有负权圈(BellmanFord不能处理)
81     int MincostMaxflow(int s, int t, long long& cost){
82         int flow = 0;
83         cost = 0;
84         while(BellmanFord(s, t, flow, cost));
85         return flow;
86     }
87 };
原文地址:https://www.cnblogs.com/cmbyn/p/8612926.html