private void prim(int s, StringBuilder sb) {
   distTo[s] = 0;
   pq.insert(s, distTo[s]);
   while (!pq.isEmpty()) {
     int v = pq.delMin();
     if (v != s) {
       Route r = edgeTo[v];
       String str = String.format("%s, %s : %d\n", r.fst(), r.snd(), r.distance());
       sb.append(str);
     }
     scan(v);
   }
 }
 // Option 4
 public void shortestByCost(String c1, String c2) {
   System.out.println("SHORTEST COST PATH from " + c1 + " to " + c2);
   System.out.println("--------------------------------------------------------");
   City city1 = null;
   City city2 = null;
   for (int i = 0; i < numCities; i++) {
     if (cities[i].name().equals(c1)) {
       city1 = cities[i];
     }
     if (cities[i].name().equals(c2)) {
       city2 = cities[i];
     }
   }
   if (c1.equals(c2) || city1 == null || city2 == null) {
     System.out.println("Invalid city choice(s)");
     return;
   }
   costTo = new double[numCities];
   edgeTo = new Route[numCities];
   for (int i = 0; i < numCities; i++) costTo[i] = Double.POSITIVE_INFINITY;
   costTo[city1.id() - 1] = 0;
   // relax vertices in order of distance from s
   costPQ = new IndexMinPQ<Double>(numCities);
   costPQ.insert(city1.id() - 1, costTo[city1.id() - 1]);
   while (!costPQ.isEmpty()) {
     int v = costPQ.delMin();
     for (Route r : adj[v]) relaxC(r, v);
   }
   if (costTo[city2.id() - 1] == Double.POSITIVE_INFINITY) {
     System.out.println("No path");
     return;
   }
   System.out.printf("Shortest cost from %s to %s is %.2f\n", c1, c2, costTo[city2.id() - 1]);
   System.out.println("Path with edges (in reverse order):");
   City currCity = city2;
   for (Route r = edgeTo[city2.id() - 1]; r != null; r = edgeTo[currCity.id() - 1]) {
     System.out.print(currCity + " " + r.price() + " ");
     currCity = r.other(currCity);
   }
   System.out.println(currCity);
 }
 // Option 3
 public void shortestByDistance(String c1, String c2) {
   System.out.println("SHORTEST DISTANCE PATH from " + c1 + " to " + c2);
   System.out.println("--------------------------------------------------------");
   City city1 = null;
   City city2 = null;
   for (int i = 0; i < numCities; i++) {
     if (cities[i].name().equals(c1)) {
       city1 = cities[i];
     }
     if (cities[i].name().equals(c2)) {
       city2 = cities[i];
     }
   }
   if (c1.equals(c2) || city1 == null || city2 == null) {
     System.out.println("Invalid city choice(s)");
     return;
   }
   distTo = new int[numCities];
   edgeTo = new Route[numCities];
   for (int i = 0; i < numCities; i++) distTo[i] = Integer.MAX_VALUE;
   distTo[city1.id() - 1] = 0;
   // relax vertices in order of distance from s
   pq = new IndexMinPQ<Integer>(numCities);
   pq.insert(city1.id() - 1, distTo[city1.id() - 1]);
   while (!pq.isEmpty()) {
     int v = pq.delMin();
     for (Route r : adj[v]) relaxD(r, v);
   }
   if (distTo[city2.id() - 1] == Integer.MAX_VALUE) {
     System.out.println("No path");
     return;
   }
   System.out.printf("Shortest distance from %s to %s is %d\n", c1, c2, distTo[city2.id() - 1]);
   System.out.println("Path with edges (in reverse order):");
   City currCity = city2;
   for (Route r = edgeTo[city2.id() - 1]; r != null; r = edgeTo[currCity.id() - 1]) {
     System.out.print(currCity + " " + r.distance() + " ");
     currCity = r.other(currCity);
   }
   System.out.println(currCity);
 }