programming-examples/java/Data_Structures/MaxFlowDinic.java
2019-11-15 12:59:38 +01:00

81 lines
2.0 KiB
Java

import java.util.*;
import java.util.stream.Stream;
// https://en.wikipedia.org/wiki/Dinic%27s_algorithm in O(V^2 * E)
public class MaxFlowDinic {
static class Edge {
int t, rev, cap, f;
public Edge(int t, int rev, int cap) {
this.t = t;
this.rev = rev;
this.cap = cap;
}
}
public static void addEdge(List<Edge>[] graph, int s, int t, int cap) {
graph[s].add(new Edge(t, graph[t].size(), cap));
graph[t].add(new Edge(s, graph[s].size() - 1, 0));
}
static boolean dinicBfs(List<Edge>[] graph, int src, int dest, int[] dist) {
Arrays.fill(dist, -1);
dist[src] = 0;
int[] Q = new int[graph.length];
int sizeQ = 0;
Q[sizeQ++] = src;
for (int i = 0; i < sizeQ; i++) {
int u = Q[i];
for (Edge e : graph[u]) {
if (dist[e.t] < 0 && e.f < e.cap) {
dist[e.t] = dist[u] + 1;
Q[sizeQ++] = e.t;
}
}
}
return dist[dest] >= 0;
}
static int dinicDfs(List<Edge>[] graph, int[] ptr, int[] dist, int dest, int u, int f) {
if (u == dest)
return f;
for (; ptr[u] < graph[u].size(); ++ptr[u]) {
Edge e = graph[u].get(ptr[u]);
if (dist[e.t] == dist[u] + 1 && e.f < e.cap) {
int df = dinicDfs(graph, ptr, dist, dest, e.t, Math.min(f, e.cap - e.f));
if (df > 0) {
e.f += df;
graph[e.t].get(e.rev).f -= df;
return df;
}
}
}
return 0;
}
public static int maxFlow(List<Edge>[] graph, int src, int dest) {
int flow = 0;
int[] dist = new int[graph.length];
while (dinicBfs(graph, src, dest, dist)) {
int[] ptr = new int[graph.length];
while (true) {
int df = dinicDfs(graph, ptr, dist, dest, src, Integer.MAX_VALUE);
if (df == 0)
break;
flow += df;
}
}
return flow;
}
// Usage example
public static void main(String[] args) {
List<Edge>[] graph = Stream.generate(ArrayList::new).limit(3).toArray(List[]::new);
addEdge(graph, 0, 1, 3);
addEdge(graph, 0, 2, 2);
addEdge(graph, 1, 2, 2);
System.out.println(4 == maxFlow(graph, 0, 2));
}
}