Pagini recente » Cod sursa (job #954462) | Cod sursa (job #670508) | Cod sursa (job #2096102) | Cod sursa (job #676900) | Cod sursa (job #1742931)
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.*;
public class Main {
public static void main(String[] args) throws FileNotFoundException {
Scanner in = new Scanner(new FileInputStream("maxflow.in"));
int N = in.nextInt();
int M = in.nextInt();
PushRelabel MF = new PushRelabel(N);
for (int i = 0; i < M; i++) {
int a = in.nextInt();
int b = in.nextInt();
int c = in.nextInt();
MF.addDoubleEdge(a, b, c);
}
PrintWriter out = new PrintWriter(new FileOutputStream("maxflow.out"));
out.println(MF.maximumFlow(1, N));
in.close();
out.close();
}
static class PushRelabel {
private static class Edge{
int flow;
int capacity;
int node;
int next;
public Edge(int flow, int capacity, int node, int next) {
this.flow = flow;
this.capacity = capacity;
this.node = node;
this.next = next;
}
}
static private final int NIL = -1;
ArrayList<Edge> graph;
int[] head;
int[] excess, height, pointer;
boolean[] active;
int[] countHeights;
Queue<Integer> queue;
final int N;
PushRelabel(int _N){
this.N = _N;
graph = new ArrayList<>();
head = new int[N + 1];
Arrays.fill(head, NIL);
excess = new int[N + 1];
height = new int[N + 1];
pointer = new int[N + 1];
active = new boolean[N + 1];
countHeights = new int[2 * N + 1];
queue = new LinkedList<>();
}
void addEdge(int from, int to, int capacity){
graph.add(new Edge(0, capacity, to, head[from]));
head[from] = graph.size() - 1;
}
void addDoubleEdge(int from, int to, int capacity){
addEdge(from, to, capacity);
addEdge(to, from, 0);
}
private void enqueue(int v){
if(!active[v] && excess[v] > 0){
active[v] = true;
queue.add(v);
}
}
private void push(int u, int p){
Edge edge = graph.get(p);
int v = edge.node;
int delta = Math.min(excess[u], edge.capacity - edge.flow);
if (height[u] <= height[v] || delta == 0)
return;
graph.get(p).flow += delta;
graph.get(p ^ 1).flow -= delta;
excess[u] -= delta;
excess[v] += delta;
enqueue(v);
}
private void relabel(int v){
countHeights[height[v]]--;
height[v] = 2 * N;
for (int p = head[v]; p != NIL; p = graph.get(p).next) {
Edge edge = graph.get(p);
if (edge.capacity > edge.flow)
height[v] = Math.min(height[v], 1 + height[edge.node]);
}
countHeights[height[v]]++;
enqueue(v);
}
private void gap(int h){
for (int i = 1; i <= N; i++) {
if (height[i] >= h){
countHeights[height[i]]--;
height[i] = Math.max(height[i], N + 1);
countHeights[height[i]]++;
enqueue(i);
}
}
}
private void discharge(int u){
boolean doneGap = false;
while (excess[u] > 0){
if (countHeights[height[u]] == 1 && !doneGap){
gap(height[u]);
doneGap = true;
pointer[u] = NIL;
}
if (pointer[u] == NIL){
relabel(u);
pointer[u] = head[u];
}
else{
int p = pointer[u];
Edge edge = graph.get(p);
int v = edge.node;
if (height[u] >= height[v] + 1 && edge.capacity > edge.flow)
push(u, p);
else
pointer[u] = edge.next;
}
}
}
private void initPreflow(int S, int T){
Arrays.fill(countHeights, 0);
Arrays.fill(excess, 0);
Arrays.fill(height, 0);
Arrays.fill(active, false);
queue.clear();
for (int i = 1; i <= N; i++) {
pointer[i] = head[i];
}
height[S] = N;
active[S] = active[T] = true;
countHeights[N] = 1;
countHeights[0] = N - 1;
for (int p = head[S]; p != NIL; p = graph.get(p).next) {
excess[S] += graph.get(p).capacity;
push(S, p);
}
}
int maximumFlow(int S, int T){
initPreflow(S, T);
while (!queue.isEmpty()){
int v = queue.remove();
active[v] = true;
discharge(v);
}
int maxFlow = 0;
for (int p = head[S]; p != NIL; p = graph.get(p).next) {
maxFlow += graph.get(p).flow;
}
return maxFlow;
}
}
}