网络流(Network Flow)是指在一个有向图中,每条边都有一个容量(capacity),表示该边能承载的最大流量。网络流问题通常涉及从源点(source)到汇点(sink)的最大流量计算。
基本术语:
最大流问题的目标是找到从源点到汇点的最大可能流量,同时满足:
贪心算法在每一步选择当前看起来最优的解决方案,希望最终能得到全局最优解。在网络流问题中,贪心策略可以表现为:
容量缩放(Capacity Scaling)是一种优化技术,它通过优先处理高容量边来提高算法效率。基本思想是:
这种方法可以显著减少需要处理的边数,尤其是在网络中存在较大容量差异时。
import java.util.*;
public class CapacityScalingMaxFlow {
private static class Edge {
int to, rev;
long capacity;
public Edge(int to, int rev, long capacity) {
this.to = to;
this.rev = rev;
this.capacity = capacity;
}
}
private List<Edge>[] graph;
private int[] level;
private int[] iter;
private int n;
private long maxCapacity;
public CapacityScalingMaxFlow(int n) {
this.n = n;
this.graph = new ArrayList[n];
for (int i = 0; i < n; i++) {
graph[i] = new ArrayList<>();
}
this.maxCapacity = 0;
}
public void addEdge(int from, int to, long capacity) {
graph[from].add(new Edge(to, graph[to].size(), capacity));
graph[to].add(new Edge(from, graph[from].size() - 1, 0));
maxCapacity = Math.max(maxCapacity, capacity);
}
private void bfs(int s, long delta) {
Arrays.fill(level, -1);
Queue<Integer> queue = new LinkedList<>();
level[s] = 0;
queue.add(s);
while (!queue.isEmpty()) {
int v = queue.poll();
for (Edge e : graph[v]) {
if (e.capacity >= delta && level[e.to] < 0) {
level[e.to] = level[v] + 1;
queue.add(e.to);
}
}
}
}
private long dfs(int v, int t, long f, long delta) {
if (v == t) return f;
for (; iter[v] < graph[v].size(); iter[v]++) {
Edge e = graph[v].get(iter[v]);
if (e.capacity >= delta && level[v] < level[e.to]) {
long d = dfs(e.to, t, Math.min(f, e.capacity), delta);
if (d > 0) {
e.capacity -= d;
graph[e.to].get(e.rev).capacity += d;
return d;
}
}
}
return 0;
}
public long maxFlow(int s, int t) {
level = new int[n];
iter = new int[n];
long flow = 0;
// 初始Δ设为最大的2的幂次方不超过最大容量
long delta = Long.highestOneBit(maxCapacity);
while (delta > 0) {
while (true) {
bfs(s, delta);
if (level[t] < 0) break;
Arrays.fill(iter, 0);
long f;
while ((f = dfs(s, t, Long.MAX_VALUE, delta)) > 0) {
flow += f;
}
}
delta /= 2;
}
return flow;
}
public static void main(String[] args) {
// 示例使用
CapacityScalingMaxFlow flow = new CapacityScalingMaxFlow(6);
// 源点为0,汇点为5
flow.addEdge(0, 1, 16);
flow.addEdge(0, 2, 13);
flow.addEdge(1, 2, 10);
flow.addEdge(1, 3, 12);
flow.addEdge(2, 1, 4);
flow.addEdge(2, 4, 14);
flow.addEdge(3, 2, 9);
flow.addEdge(3, 5, 20);
flow.addEdge(4, 3, 7);
flow.addEdge(4, 5, 4);
System.out.println("Maximum flow: " + flow.maxFlow(0, 5));
}
}
可以结合动态树(Link-Cut Tree)数据结构将时间复杂度进一步优化到O(EV log V)
利用多线程并行处理不同Δ值的搜索过程
结合启发式方法选择更优的增广路径顺序
public class CapacityScalingTest {
public static void main(String[] args) {
testSmallNetwork();
testLargeNetwork();
testUnbalancedNetwork();
}
private static void testSmallNetwork() {
CapacityScalingMaxFlow flow = new CapacityScalingMaxFlow(4);
flow.addEdge(0, 1, 3);
flow.addEdge(0, 2, 2);
flow.addEdge(1, 2, 1);
flow.addEdge(1, 3, 3);
flow.addEdge(2, 3, 2);
long result = flow.maxFlow(0, 3);
System.out.println("Small network test - Expected: 4, Actual: " + result);
}
private static void testLargeNetwork() {
int n = 100;
CapacityScalingMaxFlow flow = new CapacityScalingMaxFlow(n);
Random rand = new Random();
// 创建随机网络
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (rand.nextDouble() < 0.1) { // 10%概率创建边
long cap = rand.nextInt(10000) + 1;
flow.addEdge(i, j, cap);
}
}
}
long result = flow.maxFlow(0, n - 1);
System.out.println("Large network test completed with flow: " + result);
}
private static void testUnbalancedNetwork() {
CapacityScalingMaxFlow flow = new CapacityScalingMaxFlow(5);
// 添加一条高容量边和其他低容量边
flow.addEdge(0, 1, 100000);
flow.addEdge(0, 2, 1);
flow.addEdge(1, 3, 100000);
flow.addEdge(2, 3, 1);
flow.addEdge(3, 4, 100000);
long result = flow.maxFlow(0, 4);
System.out.println("Unbalanced network test - Expected: 100000, Actual: " + result);
}
}
可以针对不同规模的网络进行性能测试,比较容量缩放优化前后的运行时间:
public class PerformanceTest {
public static void main(String[] args) {
int[] sizes = {50, 100, 200, 500};
for (int size : sizes) {
System.out.println("Testing network size: " + size);
testPerformance(size);
}
}
private static void testPerformance(int n) {
// 创建随机网络
CapacityScalingMaxFlow flow = new CapacityScalingMaxFlow(n);
Random rand = new Random();
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (rand.nextDouble() < 0.2) {
long cap = rand.nextInt(1000000) + 1;
flow.addEdge(i, j, cap);
}
}
}
long start = System.currentTimeMillis();
long result = flow.maxFlow(0, n - 1);
long end = System.currentTimeMillis();
System.out.println("Size: " + n + ", Flow: " + result +
", Time: " + (end - start) + "ms");
}
}
贪心算法在网络流容量缩放优化中的应用体现了"高容量边优先处理"这一直观而有效的策略。通过Java实现,我们可以看到:
这种算法不仅理论上有良好的时间复杂度,在实际应用中也表现出色,特别是在需要处理大规模网络流的场景中。