@Override
    public void foundShortcut(
        int u_fromNode,
        int w_toNode,
        double existingDirectWeight,
        EdgeIterator outgoingEdges,
        int skippedEdge1,
        int incomingEdgeOrigCount) {
      // FOUND shortcut
      // but be sure that it is the only shortcut in the collection
      // and also in the graph for u->w. If existing AND identical weight => update setProperties.
      // Hint: shortcuts are always one-way due to distinct level of every node but we don't
      // know yet the levels so we need to determine the correct direction or if both directions
      // minor improvement: if (shortcuts.containsKey(sc)
      // then two shortcuts with the same nodes (u<->n.endNode) exists => check current shortcut
      // against both
      Shortcut sc = new Shortcut(u_fromNode, w_toNode, existingDirectWeight);
      if (shortcuts.containsKey(sc)) {
        return;
      } else {
        Shortcut tmpSc = new Shortcut(w_toNode, u_fromNode, existingDirectWeight);
        Shortcut tmpRetSc = shortcuts.get(tmpSc);
        if (tmpRetSc != null) {
          tmpRetSc.flags = scBothDir;
          return;
        }
      }

      shortcuts.put(sc, sc);
      sc.skippedEdge1 = skippedEdge1;
      sc.skippedEdge2 = outgoingEdges.getEdge();
      sc.originalEdges = incomingEdgeOrigCount + getOrigEdgeCount(outgoingEdges.getEdge());
    }
  /** Finds shortcuts, does not change the underlying graph. */
  void findShortcuts(ShortcutHandler sch) {
    long tmpDegreeCounter = 0;
    EdgeIterator incomingEdges = vehicleInExplorer.setBaseNode(sch.getNode());
    // collect outgoing nodes (goal-nodes) only once
    while (incomingEdges.next()) {
      int u_fromNode = incomingEdges.getAdjNode();
      // accept only uncontracted nodes
      if (g.getLevel(u_fromNode) != 0) continue;

      double v_u_weight = incomingEdges.getDistance();
      int skippedEdge1 = incomingEdges.getEdge();
      int incomingEdgeOrigCount = getOrigEdgeCount(skippedEdge1);
      // collect outgoing nodes (goal-nodes) only once
      EdgeIterator outgoingEdges = vehicleOutExplorer.setBaseNode(sch.getNode());
      // force fresh maps etc as this cannot be determined by from node alone (e.g. same from node
      // but different avoidNode)
      algo.clear();
      tmpDegreeCounter++;
      while (outgoingEdges.next()) {
        int w_toNode = outgoingEdges.getAdjNode();
        // add only uncontracted nodes
        if (g.getLevel(w_toNode) != 0 || u_fromNode == w_toNode) {
          continue;
        }

        // Limit weight as ferries or forbidden edges can increase local search too much.
        // If we decrease the correct weight we only explore less and introduce more shortcuts.
        // I.e. no change to accuracy is made.
        double existingDirectWeight = v_u_weight + outgoingEdges.getDistance();
        algo.setLimitWeight(existingDirectWeight)
            .setLimitVisitedNodes((int) meanDegree * 100)
            .setEdgeFilter(levelEdgeFilter.setAvoidNode(sch.getNode()));

        dijkstraSW.start();
        dijkstraCount++;
        int endNode = algo.findEndNode(u_fromNode, w_toNode);
        dijkstraSW.stop();

        // compare end node as the limit could force dijkstra to finish earlier
        if (endNode == w_toNode && algo.getWeight(endNode) <= existingDirectWeight)
          // FOUND witness path, so do not add shortcut
          continue;

        sch.foundShortcut(
            u_fromNode,
            w_toNode,
            existingDirectWeight,
            outgoingEdges,
            skippedEdge1,
            incomingEdgeOrigCount);
      }
    }
    if (sch instanceof AddShortcutHandler) {
      // sliding mean value when using "*2" => slower changes
      meanDegree = (meanDegree * 2 + tmpDegreeCounter) / 3;
      // meanDegree = (meanDegree + tmpDegreeCounter) / 2;
    }
  }
 boolean prepareEdges() {
   // In CH the setProperties (speed) are ignored as calculating the new setProperties for a
   // shortcut is often not possible.
   // Also several shortcuts would be necessary with the different modes (e.g. fastest and
   // shortest)
   // So calculate the weight and store this as weight, then use only weight instead of calcWeight
   EdgeIterator iter = g.getAllEdges();
   int c = 0;
   while (iter.next()) {
     c++;
     iter.setDistance(prepareWeighting.calcWeight(iter));
     setOrigEdgeCount(iter.getEdge(), 1);
   }
   return c > 0;
 }
 @Override
 public void foundShortcut(
     int u_fromNode,
     int w_toNode,
     double existingDirectWeight,
     EdgeIterator outgoingEdges,
     int skippedEdge1,
     int incomingEdgeOrigCount) {
   shortcuts++;
   originalEdgesCount += incomingEdgeOrigCount + getOrigEdgeCount(outgoingEdges.getEdge());
 }
  public String BFS(Graph g, Vertex start, Vertex end, LinkedList<String> strToParse) {
    String parsed = "";
    LinkedList<VISTriple> q = new LinkedList<VISTriple>();
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

    // System.out.println("parsed: " + parsed);

    q.push(new VISTriple(0, start, ""));
    // System.out.println(q.peek().ver);

    while (!q.isEmpty()) {
      try {
        // reader.readLine();
      } catch (Exception e) {
      }

      VISTriple v = q.removeFirst();
      // System.out.println("WHILE: " + v);

      LinkedList<Edge> successors = new LinkedList<Edge>();
      successors.clear();

      EdgeIterator ei = g.incidentEdges(v.ver);
      // System.out.println("Getting incident edges:");
      while (ei.hasNext()) {
        Edge temp = ei.nextEdge();
        if (g.origin(temp) == v.ver) {
          successors.addFirst(temp);
          // System.out.println(successors.peekFirst().toString());
        }
      }

      if (v.ind >= strToParse.size() && v.ver.equals(end)) {
        // System.out.println("*result: " + v.result);
        return v.result;
      }

      String toFind = "";
      if (v.ind < strToParse.size()) {
        toFind = strToParse.get(v.ind);
      } else toFind = "";

      // System.out.println("toFind: " + toFind);

      for (int i = 0; i < successors.size(); i++) {
        Edge e = successors.get(i);
        EdgeTuple tempET = (EdgeTuple) e.element();
        // System.out.println("tempET: " + tempET);
        if (tempET.lhs.equals("") || tempET.lhs.equals(toFind)) {
          Vertex w = g.destination(e);
          if (tempET.lhs.equals(toFind)) {
            q.addFirst(new VISTriple(v.ind + 1, w, v.result + tempET.rhs));
            // System.out.println("found LHS: " + q.peekFirst());
          } else {
            q.addFirst(new VISTriple(v.ind, w, v.result + tempET.rhs));
            // System.out.println("!found LHS: " + q.peekFirst());
          }
        } // end if
      } // end for
    } // end while
    return "";
  } // end BFS