400 likes | 416 Views
Dive into single-source shortest path variations, optimal substructure, triangle inequality, and Prim’s algorithm - with examples, theorems, and detailed steps for Dijkstra’s algorithm.
E N D
CS 3343: Analysis of Algorithms Single source shortest path problem
Variations: • Single source, single destination • Single source, all destinations • Single destination, all sources • All pairs • Solving 1 is asymptotically the same as solving 2 • 2 and 3 are equivalent • 4 is different
. Example: v1 v3 v5 4 –2 –5 1 v2 v4 w(p) = –2 Paths in graphs Consider a directed graph G = (V, E) with edge-weight function w : E R. The weight of path p = v1 v2 ... vk is defined to be Sometimes we use distance instead of weight when all edge weights are non-negative, which is the case in this lecture.
Shortest paths A shortest path from u to v is a path of minimum weight from u to v. The shortest-path weight from u to v is defined as d(u, v) = min{w(p) :p is a path from u to v}. Note:d(u, v) = ¥if no path from u to v exists.
s u v t Optimal substructure Theorem. A subpath of a shortest path is a shortest path. Proof. If the subpath between u and v is not the shortest, we can replace it with a shorter one and get a shorter path from s to t than the shortest path
Proof. • d(u,v) minimizes over all paths from u to v • Concatenating two shortest paths from u to x and from x to v yields one specific path from u to v d(u, v) u v d(u, x) d(x, v) x Triangle inequality Theorem. For all u, v,xÎV, we have d(u, v) £d(u, x) + d(x, v).
Example: … < 0 u v Well-definedness of shortest paths If a graph G contains a negative-weight cycle, then some shortest paths may not exist.
Single-source shortest paths Problem. From a given source vertexsÎV, find the shortest-path weights d(s, v) for all vÎV. If all edge weights w(u, v) are nonnegative, all shortest-path weights must exist.
Idea Similar to Prim’s algorithm for MST • Starting from the source, gradually increase the search radius. Each time include a vertex that can be reached within a certain distance • Similarity to Prim’s MST: • Maintain a list of (explored) vertices whose shortest path weights are known and are within the search radius • Also maintain a list of estimated shortest distance for all other vertices (discovered and not discovered). • Select a (discovered) vertex with the minimum estimated shortest path to be added in. • Update the estimated distances for other (discovered) vertices.
55 50 55 Need at most 42 miles 10 40 5 42 30 20 12 Need at least 42 miles (triangle inequality) 30 20 25 25 50 30 Need at most 50 miles 25 50 25 50 45 • Shortest paths from source (blue) to cities within <= 40 miles have been found (inside the circle) • All cities inside the circle can be reached within <= 40 miles • All cities outside the circle are >= 40 miles away • Compute d[v], upper-bound for the shortest distance to cities that are directly connected to cities in the circle. • The smallest d[v] among all cities outside the circle is also the lower-bound for the shortest distance to these cities
49 55 7 55 50 10 40 42 30 20 30 10 20 25 25 50 30 25 50 25 50 45 • All cities inside the circle can be reached within <= 42 miles • All cities outside the circle are >= 42 miles away • Update d[v] for the vertices that are connected with the yellow vertex Important: for this idea to work, all edge weights must be non-negative
Dijkstra’s algorithm d[v] = ¥ for all vÎV ⊳ d: shortest path length d[s] = 0 ⊳ s: source S = ⊳set of explored nodes Q = V ⊳Q: a priority queue maintainingunexplored nodes whileQ ¹do u = ExtractMin (Q) ⊳ u: node to be explored S = SÈ {u} for each vÎAdj[u] do if d[v] > d[u] + w(u, v) then changeKey(v,d[u] + w(u, v)) P[v] = u relaxation step Remember predecessor on path
Q= V PRIM’s algorithm • key[v] = ¥ for all vÎV • key[r] = 0 for some arbitrary rÎV • whileQ¹ • u ExtractMin(Q) • for each vÎAdj[u] • ifvÎQ and key[v] > w(u, v) • ChangeKey(v,w(u, v)) • P[v] = u; Dijkstra’s algorithm d[v] = ¥ for all vÎV d[s] = 0 S = Q = V whileQ ¹do u = ExtractMin (Q) S = SÈ {u} for each vÎAdj[u] do if d[v] > d[u] + w(u, v) then changeKey(v,d[u] + w(u, v)) P[v] = u It suffices to only check vÎ Q, but it doesn’t hurt to check all v relaxation step Remember path
Example of Dijkstra’s algorithm 2 B D Graph with nonnegative edge weights: 10 8 A 1 4 7 9 3 C E 2 whileQ ¹do u = ExtractMin(Q) S = SÈ {u} for each vÎAdj[u] do if d[v] > d[u] + w(u, v) then changeKey(v,d[u] + w(u, v)) P[v] = u
Example of Dijkstra’s algorithm ¥ ¥ 2 Initialize: B D 10 8 A S: {} 0 1 4 7 9 3 C E 2 Q: A B C D E ¥ ¥ ¥ ¥ ¥ ¥ 0 whileQ ¹do u = ExtractMin(Q) S = SÈ {u} for each vÎAdj[u] do if d[v] > d[u] + w(u, v) then changeKey(v,d[u] + w(u, v)) P[v] = u
Example of Dijkstra’s algorithm ¥ ¥ 2 “A”EXTRACT-MIN(Q): B D 10 8 A S: { A } 0 1 4 7 9 3 C E 2 Q: A B C D E ¥ ¥ ¥ ¥ ¥ ¥ 0 whileQ ¹do u = ExtractMin(Q) S = SÈ {u} for each vÎAdj[u] do if d[v] > d[u] + w(u, v) then changeKey(v,d[u] + w(u, v)) P[v] = u
Example of Dijkstra’s algorithm ¥ 10 2 Relax all edges leaving A: B D 10 8 A S: { A } 0 1 4 7 9 3 C E 2 Q: A B C D E ¥ 3 ¥ ¥ ¥ ¥ 0 whileQ ¹do u = ExtractMin(Q) S = SÈ {u} for each vÎAdj[u] do if d[v] > d[u] + w(u, v) then changeKey(v,d[u] + w(u, v)) P[v] = u 3 - - 10
Example of Dijkstra’s algorithm ¥ 10 2 “C”EXTRACT-MIN(Q): B D 10 8 A S: { A, C } 0 1 4 7 9 3 C E 2 Q: A B C D E ¥ 3 ¥ ¥ ¥ ¥ 0 whileQ ¹do u = ExtractMin(Q) S = SÈ {u} for each vÎAdj[u] do if d[v] > d[u] + w(u, v) then changeKey(v,d[u] + w(u, v)) P[v] = u 3 - - 10
Example of Dijkstra’s algorithm 7 11 2 Relax all edges leaving C: B D 10 8 A S: { A, C } 0 1 4 7 9 3 C E 2 Q: A B C D E 3 5 ¥ ¥ ¥ ¥ 0 whileQ ¹do u = ExtractMin(Q) S = SÈ {u} for each vÎAdj[u] do if d[v] > d[u] + w(u, v) then changeKey(v,d[u] + w(u, v)) P[v] = u 3 - - 10 7 11 5
Example of Dijkstra’s algorithm 7 11 2 “E”EXTRACT-MIN(Q): B D 10 8 A S: { A, C, E } 0 1 4 7 9 3 C E 2 Q: A B C D E 3 5 ¥ ¥ ¥ ¥ 0 whileQ ¹do u = ExtractMin(Q) S = SÈ {u} for each vÎAdj[u] do if d[v] > d[u] + w(u, v) then changeKey(v,d[u] + w(u, v)) P[v] = u 3 - - 10 7 11 5
Example of Dijkstra’s algorithm 7 11 2 Relax all edges leaving E: B D 10 8 A S: { A, C, E } 0 1 4 7 9 3 C E 2 Q: A B C D E 3 5 ¥ ¥ ¥ ¥ 0 whileQ ¹do u = ExtractMin(Q) S = SÈ {u} for each vÎAdj[u] do if d[v] > d[u] + w(u, v) then changeKey(v,d[u] + w(u, v)) P[v] = u 3 ¥ ¥ 10 7 11 5 7 11
Example of Dijkstra’s algorithm 7 11 2 “B”EXTRACT-MIN(Q): B D 10 8 A S: { A, C, E, B } 0 1 4 7 9 3 C E 2 Q: A B C D E 3 5 ¥ ¥ ¥ ¥ 0 whileQ ¹do u = ExtractMin(Q) S = SÈ {u} for each vÎAdj[u] do if d[v] > d[u] + w(u, v) then changeKey(v,d[u] + w(u, v)) P[v] = u 3 ¥ ¥ 10 7 11 5 7 11
Example of Dijkstra’s algorithm 7 9 2 Relax all edges leaving B: B D 10 8 A S: { A, C, E, B } 0 1 4 7 9 3 C E 2 Q: A B C D E 3 5 ¥ ¥ ¥ ¥ 0 whileQ ¹do u = ExtractMin(Q) S = SÈ {u} for each vÎAdj[u] do if d[v] > d[u] + w(u, v) then changeKey(v,d[u] + w(u, v)) P[v] = u 3 ¥ ¥ 10 7 11 5 7 11 9
Example of Dijkstra’s algorithm 7 9 2 “D”EXTRACT-MIN(Q): B D 10 8 A S: { A, C, E, B, D} 0 1 4 7 9 3 C E 2 Q: A B C D E 3 5 ¥ ¥ ¥ ¥ 0 whileQ ¹do u = ExtractMin(Q) S = SÈ {u} for each vÎAdj[u] do if d[v] > d[u] + w(u, v) then changeKey(v,d[u] + w(u, v)) P[v] = u 3 ¥ ¥ 10 7 11 5 7 11 9
n times degree(u) times Analysis of Dijkstra whileQ ¹do u = EXTRACTMIN(Q) S = SÈ {u} for each vÎAdj[u] do if d[v] > d[u] + w(u, v) then ChangeKey(v,d[u] + w(u, v)) Total: Q(m)ChangeKEY’s. Time = Q(n)·TEXTRACTMIN + Q(m)·TChangeKEY Note: Same formula as in the analysis of Prim’s minimum spanning tree algorithm.
Analysis of Dijkstra (continued) Time = Q(n)·TEXTRACTMIN + Q(m)·TChangeKEY Q TEXTRACTMIN TChangeKEY Total array Θ(n) Θ(1) Θ(n2) Priority queue Θ(logn) Θ(logn) Θ(mlogn)
Unweighted graphs Suppose w(u, v) = 1 for all (u, v) ÎE. Can the code for Dijkstra be improved? • Use a simple FIFO queue instead of a priority queue. • Also known as breadth-first search whileQ ¹ do u= DEQUEUE(Q) for each vÎAdj[u] do if d[v] = ¥ then d[v] d[u] + 1 ENQUEUE(Q, v)
Example of breadth-first search a f h d b g e i c Q:
Example of breadth-first search a f h 0 d b g e i c 0 Q: a
Example of breadth-first search a f h 0 1 d b g 1 e i c 1 1 Q: a b d
Example of breadth-first search a f h 0 1 d b g 1 e i c 2 2 1 2 2 Q: a b d c e
Example of breadth-first search a f h 0 1 d b g 1 e i c 2 2 2 2 Q: a bd c e
Example of breadth-first search a f h 0 1 d b g 1 e i c 2 2 2 Q: a bdc e
Example of breadth-first search a f h 0 1 d 3 b g 1 e i c 2 3 2 3 3 Q: a bdce g i
Example of breadth-first search 4 a f h 0 1 d 3 b g 1 e i c 2 3 2 3 4 Q: a bdceg i f
Example of breadth-first search 4 4 a f h 0 1 d 3 b g 1 e i c 2 3 2 4 4 Q: a bdcegi f h
Example of breadth-first search 4 4 a f h 0 1 d 3 b g 1 e i c 2 3 2 4 Q: a bdcegi f h
Example of breadth-first search 4 4 a f h 0 1 d 3 b g 1 e i c 2 3 2 Q: a bdcegi fh
Example of breadth-first search 4 4 a f h 0 1 d 3 b g 1 e i c 2 3 2 Q: a bdcegi fh
Time complexity of BFS whileQ ¹ do u= DEQUEUE(Q) for each vÎAdj[u] do if d[v] = ¥ then d[v] d[u] + 1 ENQUEUE(Q, v) Total: Q(m)ENQUEUE’s and Q(n) DEQUEUE’s Time = Q(n+m) Note: using a stack instead of a queue would turn this into depth-first search