import java.util.*; import java.util.stream.Stream; public class MinCostFlowDense { static class Edge { int to, f, cap, cost, rev; Edge(int to, int cap, int cost, int rev) { this.to = to; this.cap = cap; this.cost = cost; this.rev = rev; } } public static void addEdge(List[] graph, int s, int t, int cap, int cost) { graph[s].add(new Edge(t, cap, cost, graph[t].size())); graph[t].add(new Edge(s, 0, -cost, graph[s].size() - 1)); } static void bellmanFord(List[] graph, int s, int[] dist) { int n = graph.length; Arrays.fill(dist, Integer.MAX_VALUE); dist[s] = 0; boolean[] inqueue = new boolean[n]; int[] q = new int[n]; int qt = 0; q[qt++] = s; for (int qh = 0; (qh - qt) % n != 0; qh++) { int u = q[qh % n]; inqueue[u] = false; for (int i = 0; i < graph[u].size(); i++) { Edge e = graph[u].get(i); if (e.cap <= e.f) continue; int v = e.to; int ndist = dist[u] + e.cost; if (dist[v] > ndist) { dist[v] = ndist; if (!inqueue[v]) { inqueue[v] = true; q[qt++ % n] = v; } } } } } public static int[] minCostFlow(List[] graph, int s, int t, int maxf) { int n = graph.length; int[] prio = new int[n]; int[] curflow = new int[n]; int[] prevedge = new int[n]; int[] prevnode = new int[n]; int[] pot = new int[n]; // bellmanFord invocation can be skipped if edges costs are non-negative bellmanFord(graph, s, pot); int flow = 0; int flowCost = 0; while (flow < maxf) { Arrays.fill(prio, Integer.MAX_VALUE); prio[s] = 0; boolean[] finished = new boolean[n]; curflow[s] = Integer.MAX_VALUE; for (int i = 0; i < n && !finished[t]; i++) { int u = -1; for (int j = 0; j < n; j++) if (!finished[j] && (u == -1 || prio[u] > prio[j])) u = j; if (prio[u] == Integer.MAX_VALUE) break; finished[u] = true; for (int k = 0; k < graph[u].size(); k++) { Edge e = graph[u].get(k); if (e.f >= e.cap) continue; int v = e.to; int nprio = prio[u] + e.cost + pot[u] - pot[v]; if (prio[v] > nprio) { prio[v] = nprio; prevnode[v] = u; prevedge[v] = k; curflow[v] = Math.min(curflow[u], e.cap - e.f); } } } if (prio[t] == Integer.MAX_VALUE) break; for (int i = 0; i < n; i++) if (finished[i]) pot[i] += prio[i] - prio[t]; int df = Math.min(curflow[t], maxf - flow); flow += df; for (int v = t; v != s; v = prevnode[v]) { Edge e = graph[prevnode[v]].get(prevedge[v]); e.f += df; graph[v].get(e.rev).f -= df; flowCost += df * e.cost; } } return new int[]{flow, flowCost}; } // Usage example public static void main(String[] args) { List[] graph = Stream.generate(ArrayList::new).limit(3).toArray(List[]::new); addEdge(graph, 0, 1, 3, 1); addEdge(graph, 0, 2, 2, 1); addEdge(graph, 1, 2, 2, 1); int[] res = minCostFlow(graph, 0, 2, Integer.MAX_VALUE); int flow = res[0]; int flowCost = res[1]; System.out.println(4 == flow); System.out.println(6 == flowCost); } }