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.
One-way city
Forty-five intersections, I1 to I45, where I stands for intersection, numbered row by row from the top left with nine to a row. Most streets are one way, and the outer streets form a clockwise loop. Only the middle row (I19 to I27) and the middle column (I5, I14, I23, I32 and I41) go both ways, and each edge is the travel time in minutes.
A directed, weighted graph with 45 vertices and 88 edges.
With three warehouses on mostly one-way streets, which one should deliver to each intersection, and what is the longest drive?
Warehouse 1 at I1 serves 14, 2 at I18 serves 14 and 3 at I42 serves 17. The longest drive is 16, from warehouse 2 to I7.
Step by step
- Put every warehouse in the queue at 0: 1 at I1, 2 at I18 and 3 at I42. Each place goes to the warehouse that can reach it soonest, so one search serves them all.
- Take I1 from the queue. It is warehouse 1, at 0 from itself.
- I1 to I2: 0 + 3 = 3, so I2 goes to warehouse 1 at 3.
- Take I18 from the queue. It is warehouse 2, at 0 from itself.
- I18 to I17: 0 + 4 = 4, so I17 goes to warehouse 2 at 4.
- I18 to I27: 0 + 5 = 5, so I27 goes to warehouse 2 at 5.
94 more steps lead to the last one:
- Done. Every place has its nearest warehouse. One search settled 45 places. path.Dijkstra from each warehouse in turn would settle 135 between them.
Use it in Go
nearest, err := path.DijkstraMultiSource(g, "I1", "I18", "I42")
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
- New York streets, 295 vertices and 669 edges
- London streets, 274 vertices and 598 edges
- San Francisco streets, 248 vertices and 548 edges
- Rasht streets, 298 vertices and 568 edges
- Delivery area, 8 vertices and 12 edges
- Downtown grid, 20 vertices and 60 edges
- One-way city, 45 vertices and 88 edges
- Metro region, 100 vertices and 346 edges
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.