graph | Max flow
最大流算法,解决的是从一个起点到一个终点,通过任何条路径能够得到的最大流量。
有个Edmond-Karp算法:
1. BFS找到一条增广路径;算出这条路径的最小流量(所有边的最小值)increase;
2. 然后更新路径上的权重(流量),正向边加上increase,反向边减去increase;
3. 重复1,直到没有增广路径;
可以证明的是在使用最短路增广时增广过程不超过V*E次,每次BFS的时间都是O(E),所以Edmonds-Karp的时间复杂度就是O(V*E^2)。
图的BFS和DFS的时间复杂度都是O(n+e),这里指用邻接表的方式。每次出栈或者出队列,都要扫一遍该点的所有边,所有点的边集加起来就是O(e)了。
至于为什么要用反向边,这里讲得挺清楚;
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <limits.h> 5 #include <vector> 6 using namespace std; 7 8 class Maxflow { 9 public: 10 11 Maxflow() {} 12 ~Maxflow() { 13 if (pre) delete[] pre; 14 if (flow) delete[] flow; 15 if (weight) { 16 for (int i = 0; i < vertices; ++i) { 17 delete[] weight[i]; 18 } 19 delete[] weight; 20 } 21 } 22 void readGraph(string filename) { 23 freopen(filename.c_str(), "r", stdin); 24 int edges; 25 scanf("%d %d", &vertices, &edges); 26 pre = new int[vertices]; 27 flow = new int[vertices]; 28 memset(flow, 0, vertices * sizeof(int)); 29 weight = new int*[vertices]; 30 for (int i = 0; i < vertices; ++i) { 31 weight[i] = new int[vertices]; 32 memset(weight[i], 0, vertices * sizeof(int)); 33 } 34 35 for (int i = 0; i < edges; ++i) { 36 int v1, v2, w; 37 scanf("%d %d %d", &v1, &v2, &w); 38 weight[v1 - 1][v2 - 1] = w; 39 } 40 } 41 42 int maxFlow() { 43 int start = 0, end = vertices - 1; 44 int max = 0; 45 int increase = 0; 46 while ((increase = bfs(start, end)) != 0) { 47 int p = end; 48 while (p != start) { 49 int b = pre[p]; 50 weight[b][p] -= increase; 51 weight[p][b] += increase; 52 p = b; 53 } 54 max += increase; 55 } 56 return max; 57 } 58 private: 59 int bfs(int start, int end) { 60 memset(pre, -1, vertices * sizeof(int)); 61 vector<vector<int> > layers(2); 62 int cur = 0, next = 1; 63 layers[cur].push_back(start); 64 flow[start] = INT_MAX; 65 66 while (!layers[cur].empty()) { 67 layers[next].clear(); 68 for (int i = 0; i < layers[cur].size(); ++i) { 69 int v1 = layers[cur][i]; 70 for (int v2 = 0; v2 < vertices; ++v2) { 71 if (weight[v1][v2] <= 0 || pre[v2] != -1) continue; 72 pre[v2] = v1; 73 layers[next].push_back(v2); 74 flow[v2] = min(flow[v1], weight[v1][v2]); 75 if (v2 == end) return flow[v2]; 76 } 77 } 78 79 cur = !cur; 80 next = !next; 81 } 82 return 0; 83 } 84 int* pre; 85 int** weight; 86 int* flow; 87 int vertices; 88 }; 89 90 int main() { 91 Maxflow maxflow; 92 maxflow.readGraph("input.txt"); 93 cout<< maxflow.maxFlow() << endl; 94 return 0; 95 }
sample input:
1 4 5 2 1 2 40 3 1 4 20 4 2 4 20 5 2 3 30 6 3 4 10