Ford-Fulkerson算法求最大流Java实现
2017-07-07 16:31
756 查看
在最大流问题中,我们希望在不违反任何容量限制的情况下,计算出从源结点到汇点的最大流速。对于流网络中的每一个结点,遵守“流量守恒”:除了源结点与汇点之外,流入该结点的速率等于流出该结点的速率。
《算法导论》书中所给出的伪代码如下所示:
下面是一个求最大流的过程
下面是用Java的代码实现:
package Ford_Fulkerson;
/**
* 网络中的边
* @author sdu20
*
*/
public class
4000
Edge {
private int v1;
private int v2;
private int capacity;
private int flow;
public Edge(int v1,int v2,int flow,int capacity){
this.v1 = v1;
this.v2 = v2;
this.capacity = capacity;
this.flow = flow;
}
public int getV1(){
return v1;
}
public int getV2(){
return v2;
}
public int getCapacity(){
return capacity;
}
public int getFlow(){
return flow;
}
public void setFlow(int f){
flow = f;
}
}
运行截图如下
《算法导论》书中所给出的伪代码如下所示:
下面是一个求最大流的过程
下面是用Java的代码实现:
package Ford_Fulkerson;
/**
* 网络中的边
* @author sdu20
*
*/
public class
4000
Edge {
private int v1;
private int v2;
private int capacity;
private int flow;
public Edge(int v1,int v2,int flow,int capacity){
this.v1 = v1;
this.v2 = v2;
this.capacity = capacity;
this.flow = flow;
}
public int getV1(){
return v1;
}
public int getV2(){
return v2;
}
public int getCapacity(){
return capacity;
}
public int getFlow(){
return flow;
}
public void setFlow(int f){
flow = f;
}
}
package Ford_Fulkerson; /** * 残存网络中的边 * @author sdu20 * */ public class Edge2 { private int v1; private int v2; private int flow; public Edge2(int v1,int v2,int flow){ this.v1 = v1; this.v2 = v2; this.flow = flow; } public int getV1(){ return v1; } public int getV2(){ return v2; } public int getFlow(){ return flow; } public void setFlow(int f){ flow = f; } }
package Ford_Fulkerson; import java.util.*; /** * 残存网络Gf * @author sdu20 * */ public class Gf { private int vNum; private int eNum; private LinkedList<Edge2>[] GLists; public Gf(int n){ vNum = n; eNum = 0; GLists = new LinkedList ; for(int i = 0;i<n;i++) GLists[i] = new LinkedList<>(); } public void insertEdge(Edge2 e){ int v1 = e.getV1(); GLists[v1].add(e); eNum++; } /** * 返回一条增广路径 * @return */ public LinkedList<Integer> augmentingPath(){ LinkedList<Integer> list = new LinkedList<>(); Queue<Integer> queue = new LinkedList<>(); int[] reached = new int[vNum]; int[] preNode = new int[vNum]; for(int i = 0;i<vNum;i++){ reached[i] = 0; preNode[i] = -1; } preNode[0] = -1; reached[0] = 1; queue.add(0); while(!queue.isEmpty()){//没有循环起来 int now = queue.poll(); LinkedList<Edge2> inlist = (LinkedList<Edge2>) GLists[now].clone(); while(!inlist.isEmpty()){ Edge2 e = inlist.pop(); int v2 = e.getV2(); if(reached[v2]==0){ queue.add(v2); reached[v2] = 1; preNode[v2] = now; } } } for(int i = 0;i<vNum;i++){ System.out.println(reached[i]+" "+preNode[i]); } if(reached[vNum-1]==0){ //System.out.println("here"); return list; } int pointnum = vNum-1; while(pointnum!=-1){ list.add(0, pointnum); pointnum = preNode[pointnum]; } return list; } /** * 根据增广路径得到需要调整的值 * @param list * @return */ public int changeNum(LinkedList<Integer> list){ if(list.equals(null)) return 0; int minchange = 1000; int v1 = 0; for(int i = 1;i<list.size();i++){ int v2 = list.get(i); LinkedList<Edge2> elist = (LinkedList<Edge2>) GLists[v1].clone(); Edge2 edge = elist.pop(); while(edge.getV2()!=v2){ edge = elist.pop(); } if(minchange>edge.getFlow()) minchange = edge.getFlow(); v1 = v2; } return minchange; } public void bianli(){ System.out.println("残存网络 共 "+vNum+" 个顶点, "+eNum+" 条边"); for(int i = 0;i<vNum;i++){ if(GLists[i].size()==0){ System.out.println(i+"没有后继"); continue; } for(int j = 0;j<GLists[i].size();j++){ Edge2 e = GLists[i].get(j); System.out.println("[ "+e.getV1()+" , "+e.getV2()+" , "+e.getFlow()+" ]"); } } } }
package Ford_Fulkerson; import java.util.*; /** * 流网络 * @author sdu20 * */ public class Graph { private int vNum; private int eNum; private Gf gf; private LinkedList<Edge>[] GLists; public Graph(int n){ vNum = n; eNum = 0; GLists = new LinkedList ; for(int i = 0;i<n;i++) GLists[i] = new LinkedList<>(); } public void insertEdge(Edge e){ int v1 = e.getV1(); GLists[v1].add(e); eNum++; } // public void deleteEdge(Edge e){ // int v1 = e.getV1(); // int v2 = e.getV1(); // // } public void produceGf(){ gf = new Gf(vNum); for(int i = 0;i<vNum;i++){ LinkedList<Edge> list = (LinkedList<Edge>) GLists[i].clone(); while(!list.isEmpty()){ Edge edge = list.pop(); int v1 = edge.getV1(); int v2 = edge.getV2(); int flow = edge.getFlow(); int capacity = edge.getCapacity(); if(flow==0){ gf.insertEdge(new Edge2(v1,v2,capacity)); }else{ if(flow==capacity){ gf.insertEdge(new Edge2(v2,v1,capacity)); }else if(flow<capacity){ gf.insertEdge(new Edge2(v1,v2,capacity-flow)); gf.insertEdge(new Edge2(v2,v1,flow)); } } } } } public Gf getGf(){ return gf; } private LinkedList<Integer> augmentingPath(){ return gf.augmentingPath(); } private int changeNum(LinkedList<Integer> list){ return gf.changeNum(list); } /** * 最大流 */ public void MaxFlow(){ produceGf(); gf.bianli(); LinkedList<Integer> list = augmentingPath(); while(list.size()>0){ int changenum = changeNum(list); LinkedList<Integer> copylist = (LinkedList<Integer>) list.clone();//调试 System.out.println("list:"); while(!copylist.isEmpty()){ System.out.print(copylist.pop()+" "); } System.out.println(); System.out.println("changenum: "+changenum); int v1 = 0; for(int i = 1;i<list.size();i++){ int v2 = list.get(i); if(!GLists[v1].isEmpty()){ int j = 0; Edge e = GLists[v1].get(j); while(e.getV2()!=v2 && j<GLists[v1].size()){ e = GLists[v1].get(j); j++; } if(e.getV2()!=v2 && j==GLists[v1].size()){//调试 j = 0; e = GLists[v2].get(j); while(e.getV2()!=v1 && j<GLists[v2].size()){ e = GLists[v2].get(j); j++; } } e.setFlow(e.getFlow()+changenum); } v1 = v2; } bianli(); produceGf(); gf.bianli(); list = augmentingPath(); } } public void bianli(){ System.out.println("共有 "+vNum+" 个顶点, "+eNum+" 条边"); for(int i = 0;i<vNum;i++){ if(GLists[i].size()==0) continue; for(int j = 0;j<GLists[i].size();j++){ Edge e = GLists[i].get(j); System.out.println("[ "+e.getV1()+" , "+e.getV2()+" , "+e.getFlow()+" , "+e.getCapacity()+" ]"); } } } public void showResult(){ bianli(); int maxflow = 0; for(int i = 0;i<vNum;i++){ if(GLists[i].size()>0){ for(int j = 0;j<GLists[i].size();j++){ if(GLists[i].get(j).getV2() == vNum-1){ maxflow += GLists[i].get(j).getFlow(); } } } } System.out.println("最大流为 "+maxflow); } }
package Ford_Fulkerson; public class Main { public static void main(String[] args){ test(); } private static void test(){ Graph graph = new Graph(6); Edge[] edges = new Edge[9]; edges[0] = new Edge(0,1,0,16); edges[1] = new Edge(0,2,0,13); edges[2] = new Edge(1,3,0,12); edges[3] = new Edge(2,1,0,4); edges[4] = new Edge(2,4,0,14); edges[5] = new Edge(3,2,0,9); edges[6] = new Edge(3,5,0,20); edges[7] = new Edge(4,3,0,7); edges[8] = new Edge(4,5,0,4); for(int i = 0;i<9;i++) graph.insertEdge(edges[i]); graph.MaxFlow(); graph.showResult(); } public static void test2(){ Graph graph = new Graph(6); Edge[] edges = new Edge[9]; edges[0] = new Edge(0,1,4,16); edges[1] = new Edge(0,2,0,13); edges[2] = new Edge(1,3,4,12); edges[3] = new Edge(2,1,0,4); edges[4] = new Edge(2,4,4,14); edges[5] = new Edge(3,2,4,9); edges[6] = new Edge(3,5,0,20); edges[7] = new Edge(4,3,0,7); edges[8] = new Edge(4,5,4,4); for(int i = 0;i<9;i++) graph.insertEdge(edges[i]); graph.bianli(); graph.MaxFlow(); graph.bianli(); } }
运行截图如下
相关文章推荐
- 《网络流学习笔记02--Edmonds-Karp,Ford-Fulkerson,Dinic三种算法实现最大流》
- Ford-Fulkerson算法 java实现
- [图论]最大流介绍 Ford-Fulkerson算法 邻接表实现
- 三种算法求最大子段和问题——Java实现
- 算法学习之最大子序列算法(java实现)
- matlab实现基于DFS的Ford_Fulkerson最大流最小割算法
- 【LeetCode-面试算法经典-Java实现】【053-Maximum Subarray(最大子数组和)】
- 最大流:Ford-Fulkerson方法DFS实现
- 算法java实现--分支限界法--最大团问题
- Java实现最大公约数的算法代码
- 【算法数据结构Java实现】时间复杂度为O(n)的最大和序列
- 7. 网络流算法--Ford-Fulkerson方法及其多种实现
- 图的匹配问题与最大流问题(三)——最大流问题Ford-Fulkerson方法Java实现
- 最短路径算法比较(Dijkstra、Bellman-Ford、SPFA)及实现(Java)
- 最大子序列算法的JAVA实现
- 三种算法实现最大子段和问题(Java实现)
- Euclid算法求最大公约数--java实现
- java实现最大子序列问题——————性能最优的算法
- Java实现算法之--求子数组和的最大值
- C++代码实现Ford-Fulkerson方法Edmonds Karp算法解决最大流问题