k-center
Chooses k centers so that the vertex farthest from its nearest center is as near as it can make it.
Time complexity O(k (V+E) log V), gograph function path.KCenter.
How it works
Where should a company open k warehouses so that no address is a long drive from all of them? Trying every choice is far too slow on a city, so path.KCenter chooses them farthest first: it opens the first warehouse, then keeps opening the next one at the address farthest from every warehouse so far. Each new warehouse needs a search only over the addresses it gets closer to, and k rounds cost O(k (V+E) log V).
When every road works both ways in the same time, the longest drive this leaves is never more than twice the best any k warehouses can do. With one-way streets the drives aren't symmetric, and that factor of two isn't guaranteed.
The second warehouse often lands at the edge of the map. The method shrinks the worst drive, so it serves the most remote address first. That is the difference from k-median, which minimizes the average drive and puts warehouses nearer the busy middle.
Warehouses that are already open can be passed as fixed centers. They count toward k and open first, in the order given. Without them, the first center is the first vertex added to the graph. Which one opens first changes the rest.
Metro region
A hundred towns, T1 to T100, where T stands for town, numbered row by row from the top left with ten to a row. Two fast motorways cross at T45: one runs from T41 to T50, the other through T5, T15 and on down to T95. Local roads join neighboring towns, a few of them one way, and each edge is the travel time in minutes.
A directed, weighted graph with 100 vertices and 346 edges.
With one warehouse at T45, where should three more open so that the longest drive to any town is as short as it can be made?
Open warehouses at T45, T80, T91 and T20, in that order. The longest drive is 33.
Step by step
- No warehouse is open yet, so every drive time starts at ∞.
- Open warehouse 1 at T45, which is given. A search from it gives every place it reaches a drive time. The search goes on to T35, T44, T46 and T55.
- Take T35 from the queue. Warehouse 1 reaches it in 2, and nothing reaches it sooner. The search goes on to T25, T34 and T36. T46 already has a drive at least as quick.
- Take T55 from the queue. Warehouse 1 reaches it in 2, and nothing reaches it sooner. The search goes on to T54, T56, T65 and T66.
- Take T44 from the queue. Warehouse 1 reaches it in 3, and nothing reaches it sooner. The search goes on to T43 and T53. T34 and T54 already have a drive at least as quick.
- Take T46 from the queue. Warehouse 1 reaches it in 3, and nothing reaches it sooner. The search goes on to T47. T36 already has a drive at least as quick.
127 more steps lead to the last one:
- Warehouse 4's search is done. 8 places moved to it. 4 warehouses are open. The farthest place from every warehouse is T1, 33 from warehouse 1, so the longest drive is 33. There are 3,921,225 ways to choose 4 of the 100 places, too many to try. Some roads here are one way, so the factor of two isn't guaranteed.
Use it in Go
centers, longest, err := path.KCenter(g, 4, "T45")
if err != nil {
return err
}
for _, v := range centers {
fmt.Println(v.Label())
}
fmt.Println(longest)
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
- School run, 6 vertices and 13 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.
- Multi-source Dijkstra: Finds the nearest of several sources for every vertex, and the distance from it, in one search.
- 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.