import java.io.*;
import java.util.*;

class MaxFlow{
    private static class Edge{
        int flow;
        int capacity;
        int node;
        int next;

        Edge(int flow, int capacity, int node, int next) {
            this.flow = flow;
            this.capacity = capacity;
            this.node = node;
            this.next = next;
        }
    }

    private final int NIL = -1;

    private ArrayList<Edge> G;
    private int[] head, pointer, father;
    private int N, contor;

    MaxFlow(int N){
        this.G =  new ArrayList<>();
        this.head = new int[N + 1];
        this.pointer = new int[N + 1];
        this.father = new int[N + 1];
        this.N = N;
        this.contor = 0;

        for (int i = 1; i <= N; ++i)
            this.head[i] = NIL;
    }

    void addEdge(int x, int y, int capacity){
        G.add(new Edge(0, capacity, y, head[x]));
        head[x] = contor++;
    }

    private boolean BFS(int S, int T){
        for (int i = 1; i <= N; i++) {
            pointer[i] = 0;
            father[i] = 0;
        }

        Queue<Integer> queue = new LinkedList<>();
        queue.add(S);
        father[S] = S;

        while (!queue.isEmpty()){
            int node = queue.remove();

            for (int p = head[node]; p != NIL; p = G.get(p).next) {
                Edge e = G.get(p);
                int son = e.node;
                int flow = e.flow;
                int capacity = e.capacity;

                if (father[son] == 0 && capacity > flow){
                    father[son] = node;
                    pointer[son] = p;

                    if (son == T)
                        return true;

                    queue.add(son);
                }
            }
        }

        return false;
    }

    int maxFlow(int S, int T){
        int totalFlow = 0;

        while (BFS(S, T)){
            for (int p = head[T]; p != NIL; p = G.get(p).next) {
                int son = G.get(p).node;

                if (father[son] != 0 && G.get(p ^ 1).capacity > G.get(p ^ 1).flow){
                    father[T] = son;
                    pointer[T] = p ^ 1;

                    int fmin = Integer.MAX_VALUE;
                    int node = T;

                    while (node != S){
                        Edge e = G.get(pointer[node]);
                        fmin = Math.min(fmin, e.capacity - e.flow);
                        node = father[node];
                    }

                    totalFlow += fmin;
                    node = T;

                    while (node != S){
                        G.get(pointer[node]).flow += fmin;
                        G.get(pointer[node] ^ 1).flow -= fmin;
                        node = father[node];
                    }
                }
            }
        }

        return totalFlow;
    }
}

@@ -485,16 +485,8 @@
 nt N
-, contor
 ;%0A%0A 
@@ -674,24 +674,25 @@
 .N = N;%0A
+%0A
         
 this.con
@@ -687,93 +687,305 @@
     
-this.contor = 0;%0A
+Arrays.fill(head, NIL);
 %0A    
+%7D%0A%0A
     
-for (int i = 1; i %3C= N; ++i)%0A            this.head%5Bi%5D = NIL
+void addEdge(int x, int y, int capacity)%7B%0A        x--; y--;%0A%0A        if (!(0 %3C= x && x %3C N)) throw new AssertionError();%0A        if (!(0 %3C= y && y %3C N)) throw new AssertionError();%0A%0A        G.add(new Edge(0, capacity, y, head%5Bx%5D));%0A        head%5Bx%5D = G.size() - 1
 ;%0A  
@@ -993,32 +993,38 @@
  %7D%0A%0A    void add
+Double
 Edge(int x, int 
@@ -1049,32 +1049,28 @@
         
-G.
 add
-(new 
 Edge(
-0
+x, y
 , capaci
@@ -1075,50 +1075,35 @@
 city
-, y, head%5Bx%5D));%0A        head%5Bx%5D = contor++
+);%0A        addEdge(y, x, 0)
 ;%0A  
@@ -1158,103 +1158,68 @@
     
-for (int i = 1; i %3C= N; i++) %7B%0A            pointer%5Bi%5D = 0;%0A            father%5Bi%5D = 0;%0A        %7D
+Arrays.fill(father, NIL);%0A        Arrays.fill(pointer, NIL);
 %0A%0A  
@@ -1638,17 +1638,19 @@
 son%5D == 
-0
+NIL
  && capa
@@ -1945,32 +1945,220 @@
 (int S, int T)%7B%0A
+        S--; T--;%0A%0A        if (!(0 %3C= S && S %3C N)) throw new AssertionError();%0A        if (!(0 %3C= T && T %3C N)) throw new AssertionError();%0A        if (S == T) throw new AssertionError();%0A%0A
         int tota
@@ -2192,24 +2192,25 @@
 BFS(S, T))%7B%0A
+%0A
             
@@ -2339,17 +2339,19 @@
 son%5D != 
-0
+NIL
  && G.ge
@@ -3155,11 +3155,430 @@
 w;%0A    %7D
+%0A%0A    ArrayList%3CInteger%3E getSaturatedEdges(int node)%7B%0A        node--;%0A%0A        if (!(0 %3C= node && node %3C N)) throw new AssertionError();%0A%0A        ArrayList%3CInteger%3E list = new ArrayList%3C%3E();%0A%0A        for (int p = head%5Bnode%5D; p != NIL; p = G.get(p).next) %7B%0A            Edge e = G.get(p);%0A%0A            if (e.flow == e.capacity && e.capacity %3E 0)%0A                list.add(e.node + 1);%0A        %7D%0A%0A        return list;%0A    %7D
 %0A%7D%0A

Update MaximumFlow.java