import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
public class FordFulkerson {
static final int M = 10000; // unreachable
/**
* 查找AugmentPath(增广路径)
* <pre>
* @param edges : G(V,E)
* @param f : 当前的最大流
* @param s : 源点
* @param t : 汇点
* @return
* </pre>
*/
static int[] getAugmentPath(int[][] edges, int[][] f, int s, int t) {
int vertex = edges.length;
boolean[] visited = new boolean[vertex];
int[] p = new int[vertex];
for (int i = 0; i < vertex; i++) {
p[i] = -1;
}
visited[s] = true;
Queue<Integer> queue = new LinkedList<Integer>();
queue.add(s);
boolean exist = false;
while (!queue.isEmpty() && !exist) {
int i = queue.poll();
for (int j = 0; j < vertex; j++) {
int remain = edges[i][j] - f[i][j];
if (i != j && edges[i][j] < M && !visited[j] && remain > 0) {
visited[j] = true;
queue.offer(j);
p[j] = i;
if (j == t) {
exist = true;
break;
}
}
}
visited[i] = true;
}
if (!exist)
return null;
List<Integer> path = new ArrayList<Integer>();
path.add(t);
while (p[t] != -1) {
path.add(0, p[t]);
t = p[t];
}
int[] result = new int[path.size()];
for (int i = 0; i < path.size(); i++) {
result[i] = path.get(i);
}
return result;
}
/**
* 获得增广路径上的最小残留值
* @param edges
* @param f
* @param augmentingPath
* @return
*/
static int getMinRemain(int[][] edges, int[][] f, int[] augmentingPath) {
int remain = Integer.MAX_VALUE;
for (int i = 0; i < augmentingPath.length - 1; i++) {
int u = augmentingPath[i];
int v = augmentingPath[i + 1];
if (remain > (edges[u][v] - f[u][v]))
remain = edges[u][v] - f[u][v];
}
return remain;
}
static void fordFulkerson(String[] vertexs, int[][] edges, int s, int t) {
int vertex = vertexs.length;
int[][] f = new int[vertex][vertex];
int[] path = null;
while ((path = getAugmentPath(edges, f, s, t)) != null) {
int minRemain = getMinRemain(edges, f, path);
for (int i = 0; i < path.length - 1; i++) {
int u = path[i];
int v = path[i + 1];
f[u][v] = f[u][v] + minRemain;
if(f[u][v] > edges[u][v]) {
int delta = Math.min(f[u][v], f[v][u]);
f[u][v] -= delta;
f[v][u] -= delta;
}
}
}
System.out.println("Max Flow : ");
for(int i = 0; i < vertex; i++) {
for(int j = 0; j < vertex; j++) {
if(f[i][j] <= 0)
continue;
System.out.printf("%s -> %s : %d\n", vertexs[i], vertexs[j], f[i][j]);
}
}
}
public static void main(String[] args) {
// vertex name
String[] vertexs = { "s", "v1", "v2", "v3", "v4", "t" };
// capacity
int[][] edges = {
{ 0, 16, 13, M, M, M },
{ M, 0, 10, 12, M, M },
{ M, 4, 0, M, 14, M },
{ M, M, 9, 0, M, 20 },
{ M, M, M, 7, 0, 4 },
{ M, M, M, M, M, 0 } };
// source index
int s = 0;
// sink index
int t = 5;
fordFulkerson(vertexs, edges, s, t);
}
}