Network stream learning notes 02 -- Edmonds-Karp, Ford-Fulkerson, and Dinic three algorithms for maximum flow
[Hdu3rd] link: click here
The three methods are used, and the comparison shows that EK is the least, and only 46 ms is used.
[Edmonds-Karp Algorithm]
Based on the maximum flow algorithm, each BFS searches for the shortest path for augmented path and finds a residual path. Then, the residual network is extended. Do not forget the positive Augmented Network, which is equivalent to a negative reduction. You also need to save the records in the figure.
Finally, find a cutover set to get the maximum stream. Efficiency O (VE2). The simplest way to "find any path" is to use DFS, but the data will become slow if it is increased slightly, using BFS, the source and sink are saved in s and t, and the net traffic is saved in variable f.
Code:
/* Edmonds-Karp algorithms keep the Source and Sink points in s and t, and the net traffic stays in variable f */# include <math. h> # include <queue> # include <deque> # include <vector> # include <stack> # include <stdio. h> # include <ctype. h> # include <string. h> # include <stdlib. h ># include <iostream >#include <algorithm> using namespace std; # define Max (a, B) a> B? A: B # define Min (a, B) a> B? B: a # define mem (a, B) memset (a, B, sizeof (a) int dir [4] [2] = {1, 0 }, {-1.0}, {}, {0,-1 }}; const double eps = 1e-6; const double Pi = acos (-); const int maxn = 20; const int inf = 0x3f3f3f; int cap [20] [20], flow [20] [20]; // capacity. Traffic int Max_flow (int t) {int s = 1, I, j, f = 0, p [20], a [20]; // p indicates the previous node, a Indicates the quantity of defects. Mem (flow, 0); queue <int> Q; while (1) {while (! Q. empty () Q. pop (); memset (a, 0, sizeof (a); Q. push (s); a [s] = inf; while (! Q. empty () {I = Q. front (); if (I = t) break; Q. pop (); for (j = 1; j <= t; j ++) {if (I! = J &&! A [j] & cap [I] [j]> flow [I] [j]) {p [j] = I; Q. push (j); a [j] = a [I]> cap [I] [j]-flow [I] [j]? Cap [I] [j]-flow [I] [j]: a [I] ;}} if (! A [t]) return f; // If the augmented path is not found, it indicates that it is already the largest stream. For (I = t; I! = S; I = p [I]) {flow [I] [p [I]-= a [t]; flow [p [I] [I] + = a [t];} f + = a [t];} int main () {int a, B, c, n, m, ncase, cas = 1; scanf ("% d", & ncase); while (ncase --) {scanf ("% d", & n, & m); memset (cap, 0, sizeof (cap); while (m --) {scanf ("% d", & a, & B, & c); if (a = B) continue; cap [a] [B] + = c;} printf ("Case % d: % d \ n ", cas ++, Max_flow (n);} return 0 ;}
Ford-Fulkerson]
This algorithm is the basis of a large number of algorithms and has multiple implementation methods.
The Ford-Fulkerson Algorithm is an iterative algorithm. First, the stream size of all vertices in the graph is cleared, and the network stream size is also 0. In each iteration, you can find an "augument path" to increase the value of the stream. The augmented path can be seen as a path from the Source Vertex s to the sink vertex t, and more streams can be added along this path. Iteration continues until the augmented path cannot be found. At this time, there must be at least one full edge in all paths from the source point to the sink point (that is, the stream size of the edge is equal to the size of the edge ).
/* Implement the Ford-Fulkerson Algorithm neighbor table */# include <ctype. h> # include <stdio. h> # include <vector> # include <stdlib. h> # include <string. h >#include <iostream >#include <algorithm> using namespace std; const int maxn = 1101; const int inf = 0x3f3f3f; struct edge {int to, cap, rev ;}; vector <edge> G [maxn]; // The graph's adjacent table represents bool used [maxn]; // access tag void add_edge (int from, int to, int cap) {G [from]. push_back (edge) {to, cap, G [to]. size ()}); G [to]. push_back (edge) {from, 0, G [from]. size ()-1});} int dfs (int v, int t, int f) {if (v = t) return f; used [v] = true; for (int I = 0; I <G [v]. size (); I ++) {edge & e = G [v] [I]; if (! Used [e. to] & e. cap> 0) {int d = dfs (e. to, t, min (f, e. cap); if (d> 0) {e. cap-= d; G [e. to] [e. rev]. cap + = d; return d ;}}return 0 ;}int max_flow (int s, int t) {int flow = 0; for (;) {memset (used, 0, sizeof (used); int f = dfs (s, t, inf); if (f = 0) return flow; flow + = f ;}} int main () {int n, m, too, capp, revv; int tt, j = 1; scanf ("% d", & tt); while (tt --) {scanf ("% d", & m, & n); memset (G, 0, sizeof (G); for (int I = 0; I <n; I ++) {scanf ("% d", & too, & capp, & revv); add_edge (too, capp, revv );} printf ("Case % d: % d \ n", j ++, max_flow (1, m);} return 0 ;}
[Dinic algorithm]
One of the optimization algorithms for the maximum flow of the network stream, which layer the source image in each step and use DFS to increase the path. The time complexity is O (n ^ 2 * m ).
Algorithm flow
1. Calculate the hierarchy chart based on the residual volume network.
2. Use DFS in the Hierarchy Diagram for augmented until there is no augmented path.
3. Repeat the above steps until they cannot be extended.
/* The Dinic algorithm always looks for the shortest path and expands along this path */# include <math. h> # include <queue> # include <deque> # include <vector> # include <stack> # include <stdio. h> # include <ctype. h> # include <string. h> # include <stdlib. h ># include <iostream >#include <algorithm> using namespace std; # define Max (a, B) a> B? A: B # define Min (a, B) a> B? B: a # define mem (a, B) memset (a, B, sizeof (a) int dir [4] [2] = {1, 0 }, {-1.0}, {}, {0,-1 }}; const double eps = 1e-6; const double Pi = acos (-); const int maxn = 18; const int inf = 0x3f3f3f; struct edge {int from, to, cap ;}; vector <edge> EG; vector <int> G [maxn]; int n, s, t, ans; int level [maxn]; // The distance from the vertex to the Source Vertex. int cur [maxn]; // The Current Arc, void add_edge (int from, int to, int cap) {EG. push_back (edge) {from, t O, cap}); EG. push_back (edge) {to, from, 0}); G [from]. push_back (EG. size ()-2); G [to]. push_back (EG. size ()-1);} bool bfs () {mem (level,-1); queue <int> que; que. push (s); level [s] = 0; while (! Que. empty () {int v = que. front (); que. pop (); for (int I = 0; I <G [v]. size (); I ++) {edge & e = EG [G [v] [I]; if (level [e. to] =-1 & e. cap> 0) {level [e. to] = level [v] + 1; que. push (e. to) ;}}return (level [t]! =-1);} int dfs (int v, int a) {if (v = t | a = 0) return a; int flow = 0, f; for (int & I = cur [v]; I <G [v]. size (); I ++) {edge & e = EG [G [v] [I]; if (level [v] + 1 = level [e. to] & (f = dfs (e. to, Min (a, e. cap)> 0) {e. cap-= f; EG [G [v] [I] ^ 1]. cap + = f; flow + = f; a-= f; if (a = 0) break;} return flow;} void Dinic () {ans = 0; while (bfs () {mem (cur, 0); ans + = dfs (s, inf) ;}} int main () {int T, m, from,, cap, cas = 1; scanf ("% d", & T); while (T --) {scanf ("% d", & n, & m ); while (m --) {scanf ("% d", & from, & to, & cap); add_edge (from, to, cap );} s = 1, t = n; Dinic (); printf ("Case % d: % d \ n", cas ++, ans); EG. clear (); for (int I = 0; I <= n; ++ I) G [I]. clear () ;}return 0 ;}