多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > php教程 > 算法#115--最大流量問題(網絡流算法)

算法#115--最大流量問題(網絡流算法)

來源:程序員人生   發布時間:2016-12-07 08:38:38 閱讀次數:2517次

1.物理模型

請想象1組相互連接大小不1的輸油管道,每根管道有它自己的流量和容量,問從出發點到終點的最大流量是多少?以下流量圖中,深色路徑流量之和為最大路徑。如何求得,下面內容將詳細介紹。

2.數學模型

1個流量網絡,是1張邊的權重(這里稱為容量)為正的加權有向圖。1個st-流量網絡有兩個已知的頂點,即出發點s和終點t。

3.Ford-Fulkerson算法

也稱為增廣路徑算法。它的定義是:網絡中的初始流量為零,沿著任意從出發點到終點(且不含有飽和的正向邊或是空逆向邊)的增廣路徑增大流量,直到網絡中不存在這樣的路徑為止。

也即,假定x為該路徑上的所有邊中未使用容量的最小值,那末只需將所有邊的流量增大x,便可將網絡中的總流量最少增大x。反復這個進程,直到所有出發點到終點的路徑上最少有1條邊是飽和的。

4.剩余網絡

這里,與流量對應的邊的方向和流量本身相反。代碼以下FlowNetwork類。

5.代碼實現

對Ford-Fulkerson算法最簡單的實現可能就是最短增廣路徑算法了(最短指的是路徑長度最小,而非流量或是容量)。增廣路徑的查找等價于剩余網絡中的廣度優先搜索(BFS)。

public class FordFulkerson { private boolean[] marked; //在剩余網絡中是不是存在從s到v的路徑 private FlowEdge[] edgeTo; //從s到v的最短路徑上的最后1條邊 private double value; //當前最大流量 public FordFulkerson(FlowNetwork G, int s, int t) { //找出從s到t的流量網絡G的最大流量配置 while(hasAugmentingPath(G, s, t)) { //利用所有存在的增廣路徑 //計算當前的瓶頸容量 double bottle = Double.POSITIVE_INFINITY; for(int v = t; v != s; v = edgeTo[v].other(v)) { bottle = Math.min(bottle, edgeTo[v].residualCapacityTo(v)); } //增大流量 for(int v = t; v != s; v = edgeTo[v].other(v)) { edgeTo[v].addResidualFlowTo(v, bottle); } value += bottle; } } private boolean hasAugmentingPath(FlowNetwork G, int s, int t) { marked = new boolean[G.V()]; //標記路徑已知的頂點 edgeTo = new FlowEdge[G.V()]; //路徑上的最后1條邊 Queue<Integer> q = new Queue<Integer>(); marked[s] = true; //標記出發點 q.enqueue(s); //并將它入列 while(!q.isEmpty()) { int v = q.dequeue(); for(FlowEdge e : G.adj(v)) { int w = e.other(v); if(e.residualCapacityTo(w) > 0 && !marked[w]) {//(在剩余網絡中)對任意1條連接到1個未標記的頂點的邊 edgeTo[w] = e; //保持路徑上的最后1條邊 marked[w] = true; //標記w,由于路徑現在是已知的了 q.enqueue(w); //將它入列 } } } return marked[t]; } public double value() { return value; } public boolean inCut(int v) { return marked[v]; } public static void main(String[] args) { FlowNetwork G = new FlowNetwork(6); int[] from = new int[]{0, 0, 1, 1, 2, 2, 3, 4}; int[] to = new int[]{1, 2, 3, 4, 3, 4, 5, 5}; double[] capacity = new double[]{2.0, 3.0, 3.0, 1.0, 1.0, 1.0, 2.0, 3.0}; for(int i = 0; i < from.length; i++) { FlowEdge edge = new FlowEdge(from[i], to[i], capacity[i]); G.addEdge(edge); } int s = 0, t = G.V() - 1; FordFulkerson maxflow = new FordFulkerson(G, s, t); System.out.println("Max flow from " + s + " to " + t); for(int v = 0; v < G.V(); v++) { for(FlowEdge e : G.adj(v)) { if(v == e.from() && e.flow() > 0) { System.out.println(" " + e); } } } System.out.println("Max flow value = " + maxflow.value()); } }

輸出:

Max flow from 0 to 5
 0->2 3.00 2.00
 0->1 2.00 2.00
 1->4 1.00 1.00
 1->3 3.00 1.00
 2->4 1.00 1.00
 2->3 1.00 1.00
 3->5 2.00 2.00
 4->5 3.00 2.00
Max flow value = 4.0

剩余網絡類,其中的FlowEdge類的基礎是加權邊有向邊。

public class FlowNetwork { private final int V; private int E; private Bag<FlowEdge>[] adj; @SuppressWarnings("unchecked") public FlowNetwork(int V) { this.V = V; this.E = 0; adj = (Bag<FlowEdge>[]) new Bag[V]; for(int v = 0; v < V; v++) { adj[v] = new Bag<FlowEdge>(); } } public int V() { return V; } public int E() { return E; } public void addEdge(FlowEdge e) { int v = e.either(), w = e.other(v); adj[v].add(e); adj[w].add(e); E++; } public Iterable<FlowEdge> adj(int v) { return adj[v]; } public Iterable<FlowEdge> edges() { Bag<FlowEdge> b = new Bag<FlowEdge>(); for(int v = 0; v < V; v++) { for(FlowEdge e : adj[v]) { if(e.other(v) > v) { b.add(e); } } } return b; } }
public class FlowEdge { private final int v; private final int w; private final double capacity; private double flow; public FlowEdge(int v, int w, double capacity) { this.v = v; this.w = w; this.capacity = capacity; this.flow = 0; } public int from() { return v; } public int to() { return w; } public double capacity() { return capacity; } public double flow() { return flow; } public int either() { return v; } public int other(int vertex) { if(vertex == v) { return w; } else if(vertex == w) { return v; } else { throw new RuntimeException("Inconsistent edge"); } } public double residualCapacityTo(int vertex) { if(vertex == v) { return flow; } else if(vertex == w) { return capacity - flow; } else { throw new RuntimeException("Inconsistent edge"); } } public void addResidualFlowTo(int vertex, double delta) { if(vertex == v) { flow -= delta; } else if(vertex == w) { flow += delta; } else { throw new RuntimeException("Inconsistent edge"); } } public String toString() { return String.format("%d->%d %.2f %.2f", v, w, capacity, flow); } }
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 日本网站在线看 | 一区二区三区四区日韩 | 欧美最猛黑人xxxx黑人猛交 | 亚洲区精品久久一区二区三区 | 国产做人爱三级视频在线 | 欧美经典剧情系列h版在线观看 | xxx护士| 欧美一区精品二区三区 | 国产日韩精品视频一区二区三区 | 国产国产成人人免费影院 | 欧美97| 日本不卡在线一区二区三区视频 | 欧美精品人爱a欧美精品 | 欧美人在线 | 久久网站免费 | 欧美一级日韩在线观看 | 最近高清中文字幕免费 | 亚洲精品久久久久网站 | www 在线播放 | 一区一区三区产品乱码 | 波多野结衣在线视频观看 | 可以看毛片的网址 | 亚洲尤物视频 | 国产欧美综合在线一区二区三区 | 国产91色在线 | 亚洲 | 尤物视频在线观看视频 | 国产大学生露脸激情 | 最新在线观看精品国产福利片 | 黄色大片aa | 91欧美一区二区三区综合在线 | 亚洲精品高清中文字幕 | 国产v综合v亚洲欧美大另类 | 久久国产视频在线观看 | 亚洲地址一地址二地址三 | 亚洲码在线中文在线观看 | 禁视频网站在线观看漫画 | 中文字幕精品视频在线观看 | 一级做a爱 | 五月网| 日本护士xxxxxwww | 亚洲精品国产成人一区二区 |