最大流 : FordFulkerson 算法

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值