• Shortest path weight from Vertex a to b: δ(a,b)
    • infinity if b is unreachable from a, else min(PW(p))

Algorithms

initSSSP(s) // initialisation
	for each v in V 
		D[v] = infinity // or 1B
		p[v] = -1 // NULL
	D[s] = 0 // what we know so far
	
relax(u, v, w(u,v)) //relaxation operation
	if D[v] > D[u] + w(u,v) // SP can be shortened
		D[v] = D[u] + w(u,v) // relax this edge
		p[v] = u // rmb/update the predecessor
		// if necessary update some data structure

SSSP - Terminating Condition

  • algo has solved SSSP when for all edges (u,v), D[v] ≤ D[u] + w(u,v) [no edge can be relaxed further]
initSSSP(s) 
 
repeat // main loop
	select edge (u,v) in E **in arbitrary manner**
	relax(u, v, w(u,v)) 
until all edges have D[v] <= D[u] + w(u,v)
// can be very slow... BF algo does relaxations 
// in a better order!

Graph representations: choose Adj List for BFS/Bellman-Ford/Dijkstra’s, Adj Matrix for dense graphs → L12 Graphs
For All-Pairs Shortest Paths:L17 APSP

AlgorithmUsefulnessDescription
Modified BFS
O(V+E)
Unweighted graph / constant weight edges
→ find least number of edges traversed from s to others

will not consider a longer path with shorter weights
- graph can be directed / undirected
- data structure: adj list
- replace visited array with distance array D
- increase distance by 1 when moving to next vertex
Bellman Ford’s
O(VE)
1. general weighted graph
2. detect negative weight cycle
- graph can be directed / undirected
- data structure: adj list / edge list
- to detect -ve weight cycle, run the algo an extra time aft executing it for V-1 times
→ if any edge relaxes, -ve weight cycle exists
Key idea:
1. initialise
2. perform next step V-1 times:
- for every edge, if edge can be relaxed, relax and set p[v] = u

Bellman-Ford

  • worst case complete graph: E = V^2 → O(V^3)

Modified BFS

// initialisation 
for all v in V
	D[v] = INF
	p[v] = -1
Q = {s} // start from s
D[s] = 0
 
while Q is not empty // main
	u = Q.dequeue()
	// order of neighbour
	for all v adjacent to u
		// influences BFS
		if D[v] = INF
			// visitation sequence
			D[v] = D[u] + 1
			p[v] = u
			Q.enqueue(v)
  • Optimise
    • stop when no more relaxation after a pass (can flag out)
  • performance on small graphs:
    • without -ve weight cycle = OK, in O(VE)
    • with -ve weight cycle = terminates in O(VE)
    • some -ve edges, no -ve cycle = OK

Special Cases

Tree
O(V)
- BFS / DFSL13 Graph Traversal
- every path in tree is a shortest path, just traverse all nodes → spanning tree
- if neighbour is predecessor, don’t visit it
- since O(V+E) = O(V + V-1) = O(V)
Unweighted
O(V+E)
BFS only
DAG
O(V+E) + O(E)
- ToposortL13 Graph Traversal , One pass Bellman Ford’s
- can do an ordering of the vertices - topological sort (kahn’s algo)
- modify BF by replacing outermost V-1 loop to just one pass
→ only run the relaxation across all edges once in topological order
No negative weight edge
O((V+E)logV)
Dijkstra’s
- can use Bellman Ford’s but runs in O(VE)
→ for a reasonably sized weighted graph with V1000, E100000
→ E=O(V^2) in a complete simple graph, BF is really slow: O(V^3)
No negative weight cycle
O((V+E)logV) =
O(E log E)
Modified Dijkstra’s
Formal assumption: the graph has no negative weight cycle (but can have negative weight edges)
General case: weighted graph
O(VE)
Bellman Ford’s
Shortest path cost of multiple sources to same destination T- Flip all edges in the graphs (if it is directed) & perform SSSP algorithm from T
- the shortest path from vertex v to T D[v→T] is D[T→v] in our transformed graph

undirected connected weighted graph, non-negative edge weights:
- run dijkstra’s from T to get the SPs from T to all other vertices
- since the graph is undirected, reversing these paths will give the SPs from other vertices to T
- *O((V+E)logV) time

More Algorithms

AlgorithmUsefulnessDescription
Dijkstra’s
O((V+E)logV)
Graphs with no negative edge weight
Uses min-heap (Priority Queue) → L8 Heap
- Each vertex is only processed once
Key Ideas:
- maintain a set Solved of vertices whose final shortest path weights have been determined, initially Solved = {s}, source vertex s only
- repeatedly select vertex u in {V - Solved} with the min shortest path estimate D[u], add u to Solved, relax all edges out of u
- greedy algorithm → select best so far
- Vertices added to Solved in non-decreasing SP costs

* can detect if graph contains -ve edge weight:
→ reports true when it tries to update shortest dist of a vertex in PQ but is unable to find (vertex alr in solved)
→ cannot be used to differentiate between -ve edge weight and cycle
Modified Dijkstra’s
”lazy data structure” strat

O(E log E) =
O((V+E)logV)

except faster when E<O(V) (disconnected) then O(E log E) <
O(V log V)
Graphs with no negative weight cycle- Each vertex can be processed multiple times (due to presence of negative edge weight)
- runs faster than Bellman Ford’s
- can be trapped if there is -ve weight cycle
→ use BF instead if high probability of -ve weight cycle
Key idea:
- Enqueue (0,s) into a normal PQ
- Remove vertex u with minimum d from PQ
[min shortest path estimate so far]
- if D[u] == d, relax all edges out of u.
if an edge (u,v) is relaxed, update D[v] & enqueue new (d,v) into PQ
- else if d > D[u], discard this inferior (d,u) pair

Dijkstra’s

relax outgoing edges from nodes close to source then relax from nodes further away

  1. Min PQ: store the shortest path estimate for a vertex v as IntegerPair(d,v) in the PQ, d = D[v] (current shortest path estimate)
  2. Enqueue all vertices as Pair(INF, v), except source (0,s) into PQ
  3. Main loop: keep removing vertex u with minimum d from PQ, add u into Solved, relax all outgoing edges
    1. update D[v] and (d,v) in PQ once edge(u,v) is relaxed
    2. use bBST to implement PQ

Modified Dijkstra’s

initSSSP(s)
 
// store pair of (dist[u], u)
PQ.enqueue((0,s))
// order: increasing dist[u]
while PQ is not empty 
	(d,u) = PQ.dequeue()
	if d == D[u] // impt check, lazy
		for each vertex v adjacent to u
			// can relax
			if D[v] > D[u] + w(u,v)
				D[v] = D[u] + w(u,v) // rlx
				PQ.enqueue(D[v], v)
				// re-enqueue this