Multi-source Dijkstra

Finds the nearest of several sources for every vertex, and the distance from it, in one search.

Time complexity O((V+E) log V), gograph function path.DijkstraMultiSource.

How it works

Multi-source Dijkstra answers which source is nearest to each vertex, such as which warehouse can reach each address soonest. It puts every source in the queue at distance 0 and then runs Dijkstra's algorithm once. Each vertex is settled by whichever source gets there first, so the areas around the sources grow together until they meet.

One search settles each vertex once, so it costs O((V+E) log V) however many sources there are. Running path.Dijkstra from each source instead settles every vertex once per source. The performance card on this page times both.

path.DijkstraMultiSource returns a NearestSources value with Source, Distance and PathTo for any vertex. When two sources are equally near, the one listed first wins, so the same sources give the same answer on every run. Distances run along the edges, from a source to the vertex. On a map with one-way streets, that is the drive from the warehouse to the address, and the drive back can differ.

San Francisco streets

The main streets of San Francisco from the Embarcadero to Van Ness Avenue and the Mission, from OpenStreetMap, with the freeways that cross SoMa. Each intersection is named after its streets, one-way streets go one way, and each edge is the minutes to drive it at the speed limit, or at 22 to 40 km/h by road type where the map has no limit.

A directed, weighted graph with 248 vertices and 548 edges.

Map data © OpenStreetMap contributors.

With warehouses in the Western Addition, SoMa and the Mission, which one should deliver to each intersection, and what is the longest drive any of them has?

Warehouse 1 at Geary Blvd & Webster St serves 55, 2 at 3rd St & Howard St serves 87 and 3 at S Van Ness Ave & Mission St serves 106. The longest drive is 4.95, from warehouse 1 to Lombard St & Fillmore St.

Step by step

  1. Put every warehouse in the queue at 0: 1 at Geary Blvd & Webster St, 2 at 3rd St & Howard St and 3 at S Van Ness Ave & Mission St. Each place goes to the warehouse that can reach it soonest, so one search serves them all.
  2. Take Geary Blvd & Webster St from the queue. It is warehouse 1, at 0 from itself.
  3. Geary Blvd & Webster St to Geary Blvd & Divisadero St: 0 + 0.97 = 0.97, so Geary Blvd & Divisadero St goes to warehouse 1 at 0.97.
  4. Geary Blvd & Webster St to Geary Blvd & Laguna St: 0 + 0.31 = 0.31, so Geary Blvd & Laguna St goes to warehouse 1 at 0.31.
  5. Geary Blvd & Webster St to Turk St & Webster St: 0 + 0.76 = 0.76, so Turk St & Webster St goes to warehouse 1 at 0.76.
  6. Geary Blvd & Webster St to Webster St & Bush St: 0 + 0.52 = 0.52, so Webster St & Bush St goes to warehouse 1 at 0.52.

551 more steps lead to the last one:

  1. Done. Every place has its nearest warehouse. One search settled 248 places. path.Dijkstra from each warehouse in turn would settle 744 between them.

Use it in Go

nearest, err := path.DijkstraMultiSource(g, "Geary Blvd & Webster St", "3rd St & Howard St", "S Van Ness Ave & Mission St")
if err != nil {
	return err
}
for _, v := range g.GetAllVertices() {
	from, ok := nearest.Source(v.Label())
	if !ok {
		continue
	}
	minutes, _ := nearest.Distance(v.Label())
	fmt.Println(v.Label(), from.Label(), minutes)
}

Example graphs

More in Shortest paths

  • Dijkstra: Finds the shortest distance from a start vertex to every other vertex when no edge weight is negative.
  • k-center: Chooses k centers so that the vertex farthest from its nearest center is as near as it can make it.
  • Bellman-Ford: Finds the shortest distance from a start vertex to every other vertex, even with negative weights, and reports a negative cycle when the start can reach one.
  • Floyd-Warshall: Finds the shortest distance between every pair of vertices, even with negative weights, by letting paths stop at one more vertex in each round.

All algorithms