1.0 - Negative-Weight Graphs
1.1 - Graphs without Negative Weight Edges
Let
be any shortest path from to in a weighted graph with no negative weight edges
For all , we must have that the path prefix
is a shortest path from to and
1.2 - Graphs with Negative-Weight Edges
-
What if our graph has negative weights?
-
Even if the graph has no negative weight cycles, Dijkstra’s algorithm might not relax edges in the right order.
-
For example might be relaxed before the shortest path to has been found.
-
Graphs with negative weights might have negative weight cycles
-
Even if a graph with negative weights has no negative-weight cycles, we need to work out how to relax edges so that we are guaranteed to find shortest paths.
1.3 - Bellman-Ford Solution
🌱 Shortest paths (of length of at least ) with negative edge weights of length can be found after relaxing all vertices times (regardless of order of edge relaxations)
-
After initialisation, we know that we have found all shortest paths that contain edges
-
After relaxing each edge in the graph 1 time, we have found all shortest paths that contain edges
-
After relaxing each edge in the graph 2 times, we have found all shortest paths that contain edges.
-
After relaxing each edge in the graph times, we have found all shortest paths that contain edges.
1.4 - Bellman-Ford Algorithm
- The Bellman-Ford algorithm uses this idea to find:
- Single-source shortest paths on directed graphs
- That may have negative edges
- Moreover, it:
- Detects negative-weight cycles (reachable from the source vertex), returning false if one is found (as shortest paths are not defined valid in negative-weight cycles)
bellman_ford(G, w, s)
// G is the graph, w is the weight function, s is the source vertex
init_single_source(G, s)
// Relax each edge V - 1 times to find shortest paths
for i = 1 to |G.V| - 1
for each edge (u, v) ∈ G.E
Relax(u, v, w)
// Check for negative-weighte cycles reachable from s
for each edge (u, v) ∈ G.E
// If the relaxation condition is met, a negative-weight cycle
// is detected
if v.d > u.d + w(u, v)
// Negative-weight cycle detected
return false
return true
1.4.1 - Bellman Ford Algorithm Analysis
- time for initialisation
- for the main relaxation loop
- for the negative-weight cycle checking algorithm
1.5 - Priority-First Search
- Dijkstra’s algorithm for finding single-source shortest paths and
- Prim’s algorithm for finding minimum spanning trees
are specialisations of a priority-first search
1.5.1 - What is a Priority-First Search
- In a priority-first search, vertices are visited in order of their priority.
- For each vertex , we calculate:
- A vertex’s priority, relative to source vertex
- The predecessor to v, in a priority-first search tree
- The algorithm uses , a priority queue of unvisited vertices with key
PriorityFirstSearch(G, s, ...)
init_single_source(G, s)
Q = G.V
while Q != ∅
u = extract_min(Q)
for each vertex v in G.adj[u]
relax(u, v, ...)
init_single_source(G, s)
for each vertex v in G.V
v.key = infinity
v.pi = nil
s.key = 0
relax(u, v, ...)
if v.key > PRIORITY
v.key = PRIORITY
v.pi = u
1.5.2 - Prim’s Algorithm as a Priority-First Search
- Instantiate PRIORITY = weight(u, v)
- is the subset of vertices in the MST under construction
- is the least weight edge connecting v to T
- is the least vertex adjacent to v on that least-weight edge
At the end, the priority-first search tree is a minimum spanning tree.
1.5.3 - Dijkstra’s Algorithm
- Instantiate PRIORITY = u.key + w(u, v)
- G.V - Q is the set of vertices already visited in order of their distance from s.
- v.key is the length of the shortest path from s to v that only uses edges adjacent to visited vertices
- v.pi is the predecessor of v on the shortest path from s to v that only used edges adjacent to visited vertices
At the end, the priority-first search tree is a shortest-path tree