算法9-5:最大流算法的Java代码
殘留網絡
在介紹最大流算法之前先介紹一下什么是殘留網絡。殘余網絡的概念有點類似于集合中的補集概念。
下圖是殘余網絡的樣例。
上面的網絡是原始網絡。以下的網絡是計算出的殘留網絡。殘留網絡的作用就是用來描寫敘述這個網絡中還剩下多少能夠利用的流量。
流量網絡
最大流算法比曾經介紹的算法都要復雜。
網絡中的每一條邊須要記錄容量和當前流量。容量是固定值,是已知條件,而當前流量在計算過程中會一直發生變化。因此,須要建立一個專門的類,用于最大流算法。
public class FlowEdge {private int v;private int w;private double capacity;private double flow;public FlowEdge(int v, int w, double capacity) {this.v = v;this.w = w;this.capacity = capacity;}public int from() {return v;}public int to() {return w;}public double capactity() {return capacity;}public double flow() {return flow;}public int other(int v) {if (v == this.v) return this.w;else return this.v;}// 返回可以添加的最大流量public double residualCapacityTo(int v) {if (v == this.v) return flow;else return capacity - flow;}// 添加這條邊的流量public void addResidualFlowTo(int v, double d) {if (v == this.v) flow -= d;else flow += d;} }
與其它的圖論算法類似,須要將圖中全部的邊替換成FlowEdge。于是得到了例如以下的類。
import java.util.LinkedList; import java.util.List;public class FlowNetwork {private int V;private List<FlowEdge>[] adj;public FlowNetwork(int V) {this.V = V;adj = new LinkedList[V];for (int i = 0; i < adj.length; i++) {adj[i] = new LinkedList();}}public Iterable<FlowEdge> adj(int v) {return adj[v];}public int V() {return V;}public void addEdge(FlowEdge e) {int v = e.from();adj[v].add(e);}@Overridepublic String toString() {String result = "";for (int i = 0; i < V; i++) {result += i + ":";for(FlowEdge e:adj[i]) {result += " " + e.toString();}result += "\n";}return result;} }
算法類
依照慣例,須要為最大流算法編寫一個專門的類。
該類的代碼例如以下:
import java.util.LinkedList; import java.util.Queue;public class FordFulkerson {private FlowEdge[] edgeTo;private double value;public FordFulkerson(FlowNetwork G, int s, int t) {// 一直添加流量直到無法再添加為止while (hasAugmentingPath(G, s, t)) {// 找出增廣路的瓶頸double bottle = Double.POSITIVE_INFINITY;int v = t;while (v != s) {bottle = Math.min(bottle, edgeTo[v].residualCapacityTo(v));v = edgeTo[v].other(v);}// 添加整條路徑的流量v = t;while (v != s) {edgeTo[v].addResidualFlowTo(v, bottle);v = edgeTo[v].other(v);}// 最大流添加value += bottle;}}public double value() {return value;}// 推斷是否有增廣路// 有增廣路的條件就是存在一條路徑,這條路徑上全部的邊都能添加流量。
private boolean hasAugmentingPath(FlowNetwork G, int s, int t) { edgeTo = new FlowEdge[G.V()]; // 注意,這句話是必需要有的。由于每次增廣路徑都不一樣。 boolean[] visited = new boolean[G.V()]; // BFS Queue<Integer> q = new LinkedList<Integer>(); q.add(s); visited[s] = true; // 注意:這句話不要遺漏 while (!q.isEmpty()) { int v = q.poll(); // 可以通過的條件是流量可以添加 for (FlowEdge e : G.adj(v)) { int w = e.other(v); if (e.residualCapacityTo(w) > 0 && !visited[w]) { edgeTo[w] = e; q.add(w); visited[w] = true; } } } // 有增廣路的條件就是S點可以到達T點。 return visited[t]; } public static void main(String[] argv) { FlowNetwork g = new FlowNetwork(4); int[] data = {0, 1, r(), 0, 2, r(), 2, 1, r(), 1, 3, r(), 2, 3, r(), 0, 3, r()}; for (int i = 0; i < data.length; i += 3) { g.addEdge(new FlowEdge(data[i], data[i + 1], data[i + 2])); } StdOut.println(new FordFulkerson(g, 0, 3).value()); } private static int r() { return StdRandom.uniform(1000); } }
轉載于:https://www.cnblogs.com/bhlsheji/p/5333962.html
總結
以上是生活随笔為你收集整理的算法9-5:最大流算法的Java代码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java-final关键字
- 下一篇: 关于数据库的备份和某个表的数据备份的相关