// Path: src/main/java/uk/me/mjt/ch/Dijkstra.java
// public enum Direction{FORWARDS,BACKWARDS};


import uk.me.mjt.ch.Dijkstra.Direction;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
            DirectedEdge newShortcut = s.cloneWithEdgeId(allNodes.getEdgeIdCounter().incrementAndGet());
            newShortcut.from.edgesFrom.add(newShortcut);
            newShortcut.to.edgesTo.add(newShortcut);
        }
        n.contractionOrder = order;
    }
    
    public ArrayList<DirectedEdge> findShortcuts(Node n) {
        findShortcutsCalls.incrementAndGet();
        ArrayList<DirectedEdge> shortcuts = new ArrayList<DirectedEdge>();
        
        HashSet<Node> destinationNodes = new HashSet<Node>();
        int maxOutTime = 0;
        for (DirectedEdge outgoing : n.edgesFrom) {
            if (!outgoing.to.isContracted()) {
                destinationNodes.add(outgoing.to);
                if (outgoing.driveTimeMs > maxOutTime)
                    maxOutTime = outgoing.driveTimeMs;
            }
        }
        
        for (DirectedEdge incoming : n.edgesTo) {
            Node startNode = incoming.from;
            if (startNode.isContracted())
                continue;
            
            List<DijkstraSolution> routed = Dijkstra.dijkstrasAlgorithm(
                    startNode,
                    new HashSet<>(destinationNodes),
                    incoming.driveTimeMs+maxOutTime,
// Path: src/main/java/uk/me/mjt/ch/Dijkstra.java
// public enum Direction{FORWARDS,BACKWARDS};


// Path: src/main/java/uk/me/mjt/ch/GraphContractor.java
import uk.me.mjt.ch.Dijkstra.Direction;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;

            DirectedEdge newShortcut = s.cloneWithEdgeId(allNodes.getEdgeIdCounter().incrementAndGet());
            newShortcut.from.edgesFrom.add(newShortcut);
            newShortcut.to.edgesTo.add(newShortcut);
        }
        n.contractionOrder = order;
    }
    
    public ArrayList<DirectedEdge> findShortcuts(Node n) {
        findShortcutsCalls.incrementAndGet();
        ArrayList<DirectedEdge> shortcuts = new ArrayList<DirectedEdge>();
        
        HashSet<Node> destinationNodes = new HashSet<Node>();
        int maxOutTime = 0;
        for (DirectedEdge outgoing : n.edgesFrom) {
            if (!outgoing.to.isContracted()) {
                destinationNodes.add(outgoing.to);
                if (outgoing.driveTimeMs > maxOutTime)
                    maxOutTime = outgoing.driveTimeMs;
            }
        }
        
        for (DirectedEdge incoming : n.edgesTo) {
            Node startNode = incoming.from;
            if (startNode.isContracted())
                continue;
            
            List<DijkstraSolution> routed = Dijkstra.dijkstrasAlgorithm(
                    startNode,
                    new HashSet<>(destinationNodes),
                    incoming.driveTimeMs+maxOutTime,
                    Direction.FORWARDS);