§ DFS and topological sorting


The proper way to solve a maze is to keep breadcrumbs! Use recursion. Recursively explore the graph, backtracking as necessary.

§ DFS on a component:


parent = { s: None}
dfs-visit(adj, s):
  for v in adj[s]:
    if v not in parent:
      parent[v] = s
      dfs-visit(adj, v)

§ visit all vertices:


dfs(vs, adj):
  parent = {}
  for s in vs:
    if s not in parent:
    parent[s] = None
    dfs-visit(adj, s)

§ Complexity


We call dfs-visit once per vertex VV. Per vertex, we pay adj(v) per vertex v. In total, we visit |E|.

§ Shortest paths?


DFS does not take the shortest path to get to a node. If you want shortest paths (in an unweighted graph), use BFS.

§ Edge classification


  1. Tree edges : visit a new vertex via that edge. Parent pointers track tree edges.
  2. forward edges : goes from node n to descendant of node n.
  3. backward edges : goes from a node n to an ancestor of node n.
  4. cross edges : all other edges. Between two non-ancestor-related nodes.

How do we know forward, back, cross edges?

§ Computing edge classifications



§ Which of these can exist in an undirected graph?



A ----> B
  ----> C

A -> C is a forward edge! If we made the above undirected, then we will have A -> B tree edge and B -> C back-edge.

§ Cycle detection


GG has a cycle iff GG's DFS has a back-edge.

§ Proof: DFS has a back edge => GG has a cycle


  tree
A -...-> X
^         |
---back---*

By definition, A -> X is connected using tree edges, and a back edge X -> A. gives us the cycle.

§ Proof: GG has a cycle => DFS has a back edge


Say we have a cycle made of k vertices x, y, z, .... assume v[0] is the first vertex in the cycle visited by the DFS. Keep labeling based on how DFS visits then as v[1], v[2], ... v[k]. The we claim the edge v[k] -> v[0] will be a backedge.

§ Topological sort


Given a DAG, order vertices so that all edges point from lower order to higher order. The algorithm is to run DFS and output the reverse order of finishing time of vertices. Why does this work?

§ Proof that topological sort works


We want to show that for an edge (u,v)(u, v) that vv finishes before uu, so that vv is ordered after uu. Remember that we sort based on reverse of finishing order.

§ Case 1: u starts before v


We will eventually visit v in the recursion for u because u -> v is an edge. So, we will have the bracketing {u (v; v) u} so we're good: we finish v before we finish u.

§ Case 2: v starts before u


We have the bracketing (v ... {u. If we were to finish u before finishing v, then v is an ancestor of u, and this gives the bracketing (v .. {u .. u} .. v) and thus the edge (u,v)(u, v) is a back-edge. But this is impossible because the graph cannot have cycles! Thus, we will still have that v finishes beofre u, giving the bracketing (v v) .. {u u}.