添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《 阿里云开发者社区用户服务协议 》和 《 阿里云开发者社区知识产权保护指引 》。如果您发现本社区中有涉嫌抄袭的内容,填写 侵权投诉表单 进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

流网络(Flow Networks)指的是一个有向图 G = (V, E),其中每条边 (u, v) ∈ E 均有一非负容量 c(u, v) ≥ 0。如果 (u, v) ∉ E 则可以规定 c(u, v) = 0。流网络中有两个特殊的顶点:源点 s (source)和汇点 t(sink)。为方便起见,假定每个顶点均处于从源点到汇点的某条路径上,就是说,对每个顶点 v ∈ E,存在一条路径 s --> v --> t。因此,图 G 为连通图,且 |E| ≥ |V| - 1。

下图展示了一个流网络实例。

设 G = (V, E) 是一个流网络,其容量函数为 c。设 s 为网络的源点,t 为汇点。G 的流的一个实值函数 f:V×V → R,且满足下列三个性质:

  • 容量限制(Capacity Constraint):对所有顶点对 u, v ∈ V,要求 f(u, v) ≤ c(u, v)。
  • 反对称性(Skew Symmetry):对所有顶点对 u, v ∈ V,要求 f(u, v) = - f(v, u)。
  • 流守恒性(Flow Conservation):对所有顶点对 u ∈ V - {s, t},要求 Σ v∈V f(u, v) = 0。
  • f(u, v) 称为从顶点 u 到顶点 v 的流,流的值定义为:|f| =Σ v∈V f(s, v),即从源点 s 出发的总流。

    最大流问题(Maximum-flow problem)中,给出源点 s 和汇点 t 的流网络 G,希望找出从 s 到 t 的最大值流。

    满足流网络的性质的实际上定义了问题的限制:

  • 经过边的流不能超过边的容量;
  • 除了源点 s 和汇点 t,对于其它所有顶点,流入量与流出量要相等;
  • 上面的图中描述的流网络可简化为下图,其中源点 s = 0,汇点 t = 5。

    上图的最大流为 23,流向如下图所示。

    Ford-Fulkerson 算法是一种解决最大流的方法,其依赖于三种重要思想:

  • 残留网络(Residual networks)
  • 增广路径(Augmenting paths)
  • 割(Cut)
  • 这些思想是最大流最小割定理的精髓,该定理用流网络的割来描述最大流的值。

    最大流最小割定理

    如果 f 是具有源点 s 和汇点 t 的流网络 G = (V, E) 中的一个流,则下列条件是等价的:

  • f 是 G 的一个最大流。
  • 残留网络 G f 不包含增广路径。
  • 对 G 的某个割 (S, T),有 |f| = c(S, T)。
  • Ford-Fulkerson 算法是一种迭代方法。开始时,对所有 u, v ∈ V 有 f(u, v) = 0,即初始状态时流的值为 0。在每次迭代中,可通过寻找一条增广路径来增加流值。增广路径可以看做是从源点 s 到汇点 t 之间的一条路径,沿该路径可以压入更多的流,从而增加流的值。反复进行这一过程,直至增广路径都被找出为止。最大流最小割定理将说明在算法终止时,这一过程可产生出最大流。

    1 FORD-FULKERSON-METHOD(G, s, t)
    2   initialize flow f to 0
    3   while there exists an augmenting path p
    4     do augment flow f along p
    5   return f

    上述伪码实现的时间复杂度为 O(max_flow * E)。

    C# 代码实现如下:

    23 Console.WriteLine(); 24 Console.WriteLine( " Graph Vertex Count : {0} " , g.VertexCount); 25 Console.WriteLine( " Graph Edge Count : {0} " , g.EdgeCount); 26 Console.WriteLine(); 28 int maxFlow = g.FordFulkerson( 0 , 5 ); 29 Console.WriteLine( " The Max Flow is : {0} " , maxFlow); 31 Console.ReadKey(); 32 } 34 class Edge 35 { 36 public Edge( int begin, int end, int weight) 37 { 38 this .Begin = begin; 39 this .End = end; 40 this .Weight = weight; 41 } 43 public int Begin { get ; private set ; } 44 public int End { get ; private set ; } 45 public int Weight { get ; private set ; } 47 public override string ToString() 48 { 49 return string .Format( 50 " Begin[{0}], End[{1}], Weight[{2}] " , 51 Begin, End, Weight); 52 } 53 } 55 class Graph 56 { 57 private Dictionary< int , List<Edge>> _adjacentEdges 58 = new Dictionary< int , List<Edge>> (); 60 public Graph( int vertexCount) 61 { 62 this .VertexCount = vertexCount; 63 } 65 public int VertexCount { get ; private set ; } 67 public IEnumerable< int > Vertices 68 { 69 get 70 { 71 return _adjacentEdges.Keys; 72 } 73 } 75 public IEnumerable<Edge> Edges 76 { 77 get 78 { 79 return _adjacentEdges.Values.SelectMany(e => e); 80 } 81 } 83 public int EdgeCount 84 { 85 get 86 { 87 return this .Edges.Count(); 88 } 89 } 91 public void AddEdge( int begin, int end, int weight) 92 { 93 if (! _adjacentEdges.ContainsKey(begin)) 94 { 95 var edges = new List<Edge> (); 96 _adjacentEdges.Add(begin, edges); 97 } 99 _adjacentEdges[begin].Add( new Edge(begin, end, weight)); 100 } 102 public int FordFulkerson( int s, int t) 103 { 104 int u, v; 106 // Create a residual graph and fill the residual graph with 107 // given capacities in the original graph as residual capacities 108 // in residual graph 109 int [,] residual = new int [VertexCount, VertexCount]; 111 // Residual graph where rGraph[i,j] indicates 112 // residual capacity of edge from i to j (if there 113 // is an edge. If rGraph[i,j] is 0, then there is not) 114 for (u = 0 ; u < VertexCount; u++ ) 115 for (v = 0 ; v < VertexCount; v++ ) 116 residual[u, v] = 0 ; 117 foreach ( var edge in this .Edges) 118 { 119 residual[edge.Begin, edge.End] = edge.Weight; 120 } 122 // This array is filled by BFS and to store path 123 int [] parent = new int [VertexCount]; 125 // There is no flow initially 126 int maxFlow = 0 ; 128 // Augment the flow while there is path from source to sink 129 while (BFS(residual, s, t, parent)) 130 { 131 // Find minimum residual capacity of the edhes along the 132 // path filled by BFS. Or we can say find the maximum flow 133 // through the path found. 134 int pathFlow = int .MaxValue; 135 for (v = t; v != s; v = parent[v]) 136 { 137 u = parent[v]; 138 pathFlow = pathFlow < residual[u, v] 139 ? pathFlow : residual[u, v]; 140 } 142 // update residual capacities of the edges and reverse edges 143 // along the path 144 for (v = t; v != s; v = parent[v]) 145 { 146 u = parent[v]; 147 residual[u, v] -= pathFlow; 148 residual[v, u] += pathFlow; 149 } 151 // Add path flow to overall flow 152 maxFlow += pathFlow; 153 } 155 // Return the overall flow 156 return maxFlow; 157 } 159 // Returns true if there is a path from source 's' to sink 't' in 160 // residual graph. Also fills parent[] to store the path. 161 private bool BFS( int [,] residual, int s, int t, int [] parent) 162 { 163 bool [] visited = new bool [VertexCount]; 164 for ( int i = 0 ; i < visited.Length; i++ ) 165 { 166 visited[i] = false ; 167 } 169 Queue< int > q = new Queue< int > (); 171 visited[s] = true ; 172 q.Enqueue(s); 173 parent[s] = - 1 ; 175 // standard BFS loop 176 while (q.Count > 0 ) 177 { 178 int u = q.Dequeue(); 180 for ( int v = 0 ; v < VertexCount; v++ ) 181 { 182 if (! visited[v] 183 && residual[u, v] > 0 ) 184 { 185 q.Enqueue(v); 186 visited[v] = true ; 187 parent[v] = u; 188 } 189 } 190 } 192 // If we reached sink in BFS starting from source, 193 // then return true, else false 194 return visited[t] == true ; 195 } 196 } 197 } 198 }
  • Introduction To Algorithm
  • Floyd-Warshall's algorithm
  • Bellman-Ford algorithm for single-source shortest paths
  • Dynamic Programming | Set 23 (Bellman–Ford Algorithm)
  • Dynamic Programming | Set 16 (Floyd Warshall Algorithm)
  • Johnson’s algorithm for All-pairs shortest paths
  • Floyd-Warshall's algorithm
  • 最短路径算法--Dijkstra算法,Bellmanford算法,Floyd算法,Johnson算法
  • QuickGraph, Graph Data Structures And Algorithms for .NET
  • CHAPTER 26: ALL-PAIRS SHORTEST PATHS
  •