@Override
  public RoutingAlgorithm createAlgo() {
    checkGraph();
    // do not change weight within DijkstraBidirectionRef => so use ShortestWeighting
    DijkstraBidirectionRef dijkstrabi =
        new DijkstraBidirectionRef(g, prepareEncoder, shortestWeighting) {
          @Override
          protected void initCollections(int nodes) {
            // algorithm with CH does not need that much memory pre allocated
            super.initCollections(Math.min(initialCollectionSize, nodes));
          }

          @Override
          protected QueryGraph createQueryGraph() {
            return new QueryGraph(graph) {
              @Override
              protected void updateDistance(EdgeIteratorState edge) {
                edge.setDistance(prepareWeighting.calcWeight(edge));
              }
            };
          }

          @Override
          public boolean finished() {
            // we need to finish BOTH searches for CH!
            if (finishedFrom && finishedTo) return true;

            // changed also the final finish condition for CH
            return currFrom.weight >= bestPath.getWeight() && currTo.weight >= bestPath.getWeight();
          }

          @Override
          public void initPath() {
            // CH changes the weight in prepareEdges to the weight
            // now we need to transform it back to the real weight
            Weighting w = createWeighting();
            bestPath = new Path4CH(graph, flagEncoder, w);
          }

          @Override
          public String getName() {
            return "dijkstrabiCH";
          }

          @Override
          public String toString() {
            return getName() + "|" + prepareWeighting;
          }
        };

    if (!removesHigher2LowerEdges) dijkstrabi.setEdgeFilter(new LevelEdgeFilter(g));

    return dijkstrabi;
  }