在总流量最大的前提下,总费用最小的流为最小费用最大流。
分别用$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 };