您的位置:首页 > 编程语言 > Java开发

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;
}
}

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();
}
}


运行截图如下

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: