1. 程式人生 > 實用技巧 >最小費用最大流

最小費用最大流

網路流的最後一步。之前已經寫了最大流的Dinic,SAP,EK這三種演算法。

  1 #include "stdafx.h"
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <queue>
  5 #include <math.h>
  6 #include <stdio.h>
  7 #include <string.h>
  8 #include <algorithm>
  9 #include <functional>
 10
11 #define MAXN 5050 12 #define INF 0x3f3f3f3f 13 #define P pair<int,int> 14 15 using namespace std; 16 17 struct edge 18 { 19 int to, cap, cost, rev; 20 }; 21 22 int n, m, s, t; 23 int u, v, c, w; 24 int maxFlow, minCost; 25 26 vector<edge> G[MAXN]; 27 int h[MAXN];
28 int dist[MAXN], prevv[MAXN], preve[MAXN]; 29 30 void addedge(int from, int to, int cap, int cost) 31 { 32 edge temp1 = { to, cap, cost, (int)G[to].size() }; 33 edge temp2 = { from, 0, -cost, (int)G[from].size() - 1 }; 34 G[from].push_back(temp1); 35 G[to].push_back(temp2);
36 } 37 38 //Dijkstra演算法實現 39 void MCMF(int s, int t, int f) 40 { 41 fill(h + 1, h + 1 + n, 0); 42 while (f > 0) 43 { 44 priority_queue<P, vector<P>, greater<P> > D; 45 memset(dist, INF, sizeof dist); 46 dist[s] = 0; D.push(P(0, s)); 47 while (!D.empty()) 48 { 49 P now = D.top(); D.pop(); 50 if (dist[now.second] < now.first) continue; 51 int v = now.second; 52 for (int i = 0; i<(int)G[v].size(); ++i) 53 { 54 edge &e = G[v][i]; 55 if (e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) 56 { 57 dist[e.to] = dist[v] + e.cost + h[v] - h[e.to]; 58 prevv[e.to] = v; 59 preve[e.to] = i; 60 D.push(P(dist[e.to], e.to)); 61 } 62 } 63 } 64 if (dist[t] == INF) break; 65 for (int i = 1; i <= n; ++i) h[i] += dist[i]; 66 int d = f; 67 for (int v = t; v != s; v = prevv[v]) 68 d = min(d, G[prevv[v]][preve[v]].cap); 69 f -= d; maxFlow += d; 70 minCost += d * h[t]; 71 for (int v = t; v != s; v = prevv[v]) 72 { 73 edge &e = G[prevv[v]][preve[v]]; 74 e.cap -= d; 75 G[v][e.rev].cap += d; 76 } 77 } 78 } 79 80 int _tmain(int argc, _TCHAR* argv[]) 81 { 82 83 cout << "節點數為:"; cin >> n; 84 cout << "邊數為:"; cin >> m; 85 cout << "源點編號為:"; cin >> s; 86 cout << "匯點編號為:"; cin >> t; 87 88 cout << "輸入 " << m << " 條邊的資訊:" << endl; 89 while (m--) 90 { 91 cout << "起點:"; cin >> u; 92 cout << "終點:"; cin >> v; 93 cout << "容量:"; cin >> c; 94 cout << "費用:"; cin >> w; 95 cout << "-----------------" << endl; 96 addedge(u, v, c, w); 97 } 98 99 MCMF(s, t, INF); 100 101 cout << "最大流為:" << maxFlow << endl; 102 cout << "最小費用為" << minCost << endl; 103 cout << endl; 104 105 system("pause"); 106 return 0; 107 }