B403: Introduction to Algorithm Design and Analysis

Is-Sink(A, k) 1 let A be |V|×|V| 2 |
Universal-Sink(A) 1 let A be |V|×|V| 2 i = j = 1 3 |

- Breadth First Search
- Start at a node s
- O(|V|+|E|) time
- Use a queue to maintain unvisited vertices
- Annotate each node u with u.d, which represents the
*shortest path*from s to u - Build a
**predecessor sub-graph**(It is actually a**tree**. Why?)

- Depth First Search
- May repeat at multiple vertices (unlike BFS)
- Annotate each vertex, u, with
**discovered**(u.d) and**finished**(u.f) times; u.d < u.f - Predecessor graph is a
*depth-first forest*

**Theorem (Parenthesis Theorem)** In any depth-first search of a directed or undirected graph G = (V,E),
for any two vertices u and v, exactly one of the following three conditions holds:

- The intervals [u.d, u.f] and [v.d, v.f] are entirely disjoint; or
- The interval [u.d, u.f] is contained entirely in [v.d, v.f], and u is a descendant of v in a depth-first tree; or
- The interval [v.d, v.f] is contained entirely in [u.d, u.f], and v is a descendant of u in a depth-first tree.

**Tree edges**: Part of the depth-first forest**Back edges**: (u.v) connecting u to an ancestor, v, of u**Forward edges**: Non-tree edge (u,v) connecting u to a descendant, b, of u**Cross edges**: All other edges

**Theorem** In depth-first search of an undirected graph every edge is either a tree edge or a back edge.

**Claim** An undirected graph is cyclic if an only if there exist back edges after a depth-first search
of the graph.

Topological-Sort(G) 1 call DFS(G) to compute finishing times v.f for each vertex v 2 as each vertex is finished, insert it onto the front of a linked list 3returnthe linked list of vertices

Why does this work?

- Give a linear-time algorithm to find the number of simple paths from vertex s to vertex t in a DAG.
- Give an algorithm that determines whether or not a give undirected graph G = (V,E) contains cycle in O(|V|) time.
- Suppose we attempt to topologically sort a graph by repeatedly removing a vertex with in-degree 0 and all its outgoing edges. Why does this work? What happens if the graph has cycles?

Strongly-Connected-Components(G) 1 call DFS(G) to compute finishing times u.f for each vertex u 2 compute G^{T}3 call DFS(G^{T}), but in the main loop of DFS, consider the vertices in order of decreasing u.f 4 output the vertices of each tree in the depth-first forest formed in line 3 as a separate strongly connected component

**Lemma** Let C and C' be distinct strongly connected components in directed graph G =
(V,E), let u, v ∈ G, let u', v' &isin C',
and suppose that G contains a path u→u'. Then G cannot also contain a path
v'→v.

**Definition** If U ⊆ V, then
d(U) = min_{u∈U} {u.d}, and
f(U) = max_{u∈U} {u.f}

**Lemma** Let C and C' be distinct strongly connected components in directed graph G =
(V,E). Suppose that there is an edge (u,v) ∈ E,
where u ∈ C and v ∈ C'.
Then f(C) > f(C').

**Corollary** Let C and C' be distinct strongly connected components in directed
graph G = (V,E). Suppose that there is an edge (u,v) ∈
E^{T}, where u ∈ C and v ∈ C'.
Then f(C) < f(C').

Given a weighted, directed graph G = (V,E), with weight
function w: E → ℜ. The **weight** w(p) of
path p = ⟨v_{0}, v_{1}, ..., v_{k}⟩ is the sum
of the weights of its constituent edges:

w(p) =
Σki=1
w(v_{i−1},v_{i})

Define the **shortest-path weight** δ(u,v) from u to v by:

δ(u,v) = { | min{w(p) : p is path u→v} | if there is a path from u to v |

∞ | otherwise |

A **shortest path** from vertex u to vertex v is any path p with weight w(p) =
δ(u,v)

**Lemma** Given a weighted, directed graph G = (V,E) with weight
function w: E → ℜ, let p = ⟨v_{0},
v_{1}, ..., v_{k}⟩ be a shortest path from
vertex v_{0} to v_{k} and, for any i and
j such that 0 ≤ i ≤ j ≤ k, let p_{ij} =
⟨v_{i}, v_{i+1}, ..., v_{j}⟩ be the subpath of p from
vertex v_{i} to v_{j}.
Then p_{ij} is a shortest path
from v_{i} to v_{j}.

**Proof** By cut-and-paste argument, as before.

- Negative weight edges are fine
- Negative weight cycles cause the problem to be ill-defined. Why?
- Shortest paths can be represented using the predecessor sub-graph (as DFS-forests and BFS-trees)

Initialize-Single-Source(G, s) 1 |
Relax(u, v, w) 1 |

Bellman-Ford(G, w, s) 1 Initialize-Single-Source(G, s) 2fori = 1to|G.V|-1 3foreach edge (u,v) ∈ G.E 4 Relax(u, v, w) 5foreach edge (u,v) ∈ G.E 6ifv.d > u.d + w(u,v) 7returnFALSE 8returnTRUE

Running Time = O(VE)

DAG-Shortest-Paths(G, w, s) 1 topologically sort the vertices of G 2 Initialize-Single-Source(G, s) 3foreach vertex u, taken in topologically sorted order 4foreach vertex v ∈ G.Adj[u] 4 Relax(u, v, w)

Running Time = Θ(V + E)

Dijkstra(G, w, s) 1 Initialize-Single-Source(G, s) 2 S = φ 3 Q = G.V 4whileQ ≠ φ 5 u = Extract-Min(Q) 6 S = S ∪ {u} 7foreach vertex v ∈ G.Adj[u] 8 Relax(u, v, w)

Running Time = O((V + E)⋅log(V))
*(O(V⋅log(V) + E) achievable)*