public Graph<V> residualGraph() {
        if (isResidualGraph) {
            return this;
        }

        final Graph<V> residualGraph = new Graph<>(true);
        for (final Map.Entry<V, SortedMap<V, Edge>> nodeEdges : adjList.entrySet()) {
            final V node = nodeEdges.getKey();
            final SortedMap<V, Edge> edges = nodeEdges.getValue();
            for (final Entry<V, Edge> nodeEdge : edges.entrySet()) {
                final Edge edge = nodeEdge.getValue();
                final Edge forwardEdge = new Edge(edge.destination, edge.capacity, edge.cost, edge.capacity - edge.flow, edge.flow);
                final Edge backwardEdge = new Edge(node, edge.capacity, edge.cost * -1, edge.flow, 0, false);
                forwardEdge.counterEdge = backwardEdge;
                backwardEdge.counterEdge = forwardEdge;
                residualGraph.addEdge(node, forwardEdge);
                residualGraph.addEdge(edge.destination, backwardEdge);
            }
        }
        residualGraph.setSourceNode(sourceNode);
        residualGraph.setSinkNode(sinkNode);
        return residualGraph;
    }
@Test
    public void testResidualGraph() {
        final Graph<Integer> residualGraph = graph.residualGraph();
        final Graph<Integer> residualGraph1 = residualGraph.residualGraph();
        assertSame(residualGraph1, residualGraph);

        final Set<Integer> nodes = residualGraph.nodes();
        assertEquals(6, nodes.size());
        assertThat(nodes, contains(-1, 0, 1, 2, 3, 99));

        Map<Integer, Graph<Integer>.Edge> edges = residualGraph.edges(0);
        assertEquals(3, edges.size());
        assertEquals(getEdge(1, 1, 3, 0, 1), edges.get(1));
        assertEquals(getEdge(3, 1, 1, 1, 0), edges.get(3));
        assertEquals(getEdge(-1, 1, 0, 1, 0, false), edges.get(-1));

        edges = residualGraph.edges(2);
        assertEquals(3, edges.size());
        assertEquals(getEdge(1, 1, 1, 1, 0), edges.get(1));
        assertEquals(getEdge(3, 1, 2, 0, 1), edges.get(3));
        assertEquals(getEdge(-1, 1, 0, 1, 0, false), edges.get(-1));

        edges = residualGraph.edges(1);
        assertEquals(3, edges.size());
        assertEquals(getEdge(0, 1, -3, 1, 0, false), edges.get(0));
        assertEquals(getEdge(2, 1, -1, 0, 0, false), edges.get(2));
        assertEquals(getEdge(99, 1, 0, 0, 1), edges.get(99));

        edges = residualGraph.edges(3);
        assertEquals(3, edges.size());
        assertEquals(getEdge(0, 1, -1, 0, 0, false), edges.get(0));
        assertEquals(getEdge(2, 1, -2, 1, 0, false), edges.get(2));
        assertEquals(getEdge(99, 1, 0, 0, 1), edges.get(99));

        assertTrue(residualGraph.isResidualGraph());
    }