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