# Representing Graphs: Undirected # Representing Graphs: Directed # Finding Universal Sink

 ``` Is-Sink(A, k) 1 let A be |V|×|V| 2 for j = 1 to |V| 3 if akj == 1 4 return FALSE 5 for i = 1 to |V| 6 if aik == 1 and i ≠ k 7 return FALSE 8 return TRUE ``` ``` Universal-Sink(A) 1 let A be |V|×|V| 2 i = j = 1 3 while i≤|V| and j≤|V| 4 if aij == 1 5 i = i + 1 6 else j = j + 1 7 if i > |V| 8 return “no universal sink” 9 elsif Is-Sink(A,i) == FALSE 10 return “no universal sink” 11 else return i “is a universal sink” ```

# Quick Recap

• 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

# Properties of DFS

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.

# DFS: Example # DFS: Four Types of Edges

• 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 ```  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
3   return the linked list of vertices
```

Why does this work?

# Questions

• 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 # Strongly Connected Components

```  Strongly-Connected-Components(G)
1   call DFS(G) to compute finishing times u.f for each vertex u
2   compute GT
3   call DFS(GT), 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
```

# Why Does the Algorithm Work?

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) = minu∈U {u.d}, and f(U) = maxu∈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) ∈ ET, where u ∈ C and v ∈ C'. Then f(C) < f(C').

# Single-Source Shortest Paths

Given a weighted, directed graph G = (V,E), with weight function w: E → ℜ. The weight w(p) of path p = ⟨v0, v1, ..., vk is the sum of the weights of its constituent edges:

w(p) = Σki=1 w(vi−1,vi)

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)

# Subpaths are Shortest Paths

Lemma Given a weighted, directed graph G = (V,E) with weight function w: E → ℜ, let p = ⟨v0, v1, ..., vk be a shortest path from vertex v0 to vk and, for any i and j such that 0 ≤ i ≤ j ≤ k, let pij = ⟨vi, vi+1, ..., vj be the subpath of p from vertex vi to vj. Then pij is a shortest path from vi to vj.

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

# Observations

• 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) # Two Key Steps

 ``` Initialize-Single-Source(G, s) 1 for each vertex v ∈ G.V 2 v.d = ∞ 3 v.π = NIL 4 s.d = 0 ``` ``` Relax(u, v, w) 1 if v.d > u.d + w(u.v) 2 v.d = u.d + w(u,v) 3 v.π = u ``` # Bellman-Ford Algorithm

```  Bellman-Ford(G, w, s)
1   Initialize-Single-Source(G, s)
2   for i = 1 to |G.V|-1
3      for each edge (u,v) ∈ G.E
4         Relax(u, v, w)
5   for each edge (u,v) ∈ G.E
6      if v.d > u.d + w(u,v)
7         return FALSE
8   return TRUE
```

Running Time = O(VE) # Shortest Path for DAGs

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

Running Time = Θ(V + E) # Dijkstra's Algorithm

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

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