private static ArrayList<ResidualEdge> findAugmentedPath(
            ArrayList<ResidualEdge>[] edges, int s, int t) {
        int n = edges.length;
        ResidualEdge[] prevE = new ResidualEdge[n];
        int[] prevV = new int[n];
        Arrays.fill(prevV, -1);
        Queue<Integer> queue = new LinkedList<Integer>();  // Java6ならArrayDequeにする
        queue.add(s);
        prevV[s] = -2;  // make sure source wont be rediscovered
        search: while (!queue.isEmpty()) {
            int v = queue.poll();
            for (ResidualEdge e : edges[v]) {
                if (e.residual > 0 && prevV[e.to] == -1) {
                    prevE[e.to] = e;
                    prevV[e.to] = v;
                    if (e.to == t) break search;
                    queue.add(e.to);
                }
            }
        }
        if (prevE[t] == null) return null;
        ArrayList<ResidualEdge> path = new ArrayList<ResidualEdge>();
        ResidualEdge e;
        for (int v = t;; v = prevV[v]) {
            e = prevE[v];
            if (e == null) break;
            path.add(e);  // 効率のためここで増加フローも計算したほうがよい
        }
        return path;
    }