# Lecture 14: Graphs and Distances

### COSC 311 Algorithms, Fall 2022

$\def\compare{ {\mathrm{compare}} } \def\swap{ {\mathrm{swap}} } \def\sort{ {\mathrm{sort}} } \def\insert{ {\mathrm{insert}} } \def\true{ {\mathrm{true}} } \def\false{ {\mathrm{false}} } \def\BubbleSort{ {\mathrm{BubbleSort}} } \def\SelectionSort{ {\mathrm{SelectionSort}} } \def\Merge{ {\mathrm{Merge}} } \def\MergeSort{ {\mathrm{MergeSort}} } \def\QuickSort{ {\mathrm{QuickSort}} } \def\Split{ {\mathrm{Split}} } \def\Multiply{ {\mathrm{Multiply}} } \def\Add{ {\mathrm{Add}} } \def\cur{ {\mathrm{cur}} }$

## Announcements

1. Midterm on Friday
• Makeup date following week
• Accommodations
2. Study guide posted
• Solutions to come (tomorrow?)

## Overview

1. Eulerian Graphs
2. Graph Exploration

## Last Time

Question. Is it possible to walk around Königsberg, cross every bridge exactly once, and return to where you started?

## BoK as a Graph Problem

Original Question. Is it possible to walk around Königsberg, cross every bridge exactly once, and return to where you started?

Rephrasing as Graph Problem. Given a graph $G = (V, E)$, is there a circuit that contains every edge $e \in E$ exactly once?

• A graph with this property is called Eulerian.

Theorem (Euler 1736). $G$ is Eulerian if and only if $G$ is connected and every vertex has even degree.

• Showed “$\implies$” direction last time

## Finding Eulerian Circuits

Assume:

• $G$ is connected and all vertices have even degrees

Strategy:

• Starting from vertex $v$, walk in any direction
• cross any edge from current location
• remove edge from future consideration
• repeat
• When stuck, reassess

## Finding a Circuit

Input:

• graph $G$
• set $V$ of vertices
• set $E$ of edges
• starting vertex $v \in V$
• assume all vertices have even degree ($G$ is even)

Output:

• a circuit $P = v_0 e_1 v_1 e_2 v_2 \cdots e_k v_k$ with $v_0 = v_k = v$
• every edge $e$ incident to $v$ is contained in $P$

## FindCircuit Subroutine

  FindCircuit(V, E, v):
cur <- v
P <- v
while deg(cur) > 0
e <- any edge in E incident to cur
(prev, cur) <- e
append e, cur to P
remove e from E
if deg(prev) = 0 then remove prev from V
endwhile
remove cur from V
return P


## Circuit Finding

Claim 1. If every vertex in $G = (V, E)$ has even degree, then FindCircuit(V, E, v) returns a circuit beginning and ending at $v$.

• Loop invariant. If $\cur \neq v$, then $\cur$ and $v$ have odd degress, while all other vertices have even degrees.
• Consequence. If $\deg(\cur) = 0$, then $\cur = v$.
• $\implies$ can only get “stuck” at starting point!

## Circuit Removal

$C =$ circuit found, removed after FindCircuit(V, E, v)

Question. What can we say about remaining graph?

Claim 2. Remaining graph $G - C$ has all even degrees.

Why?

• vertices in $G$ originally have even degree
• vertices in $C$ have even degrees
• each vertex in $G$ has even number of edges removed
• even - even = even

## Finding Eulerian Circuits

Strategy.

1. Apply FindCircuit to find a circuit $P = v_0 e_1 v_1\cdots v_k$
2. Traverse $P$
• if a vertex $v_i$ with $\deg(v_i) > 0$ is encountered,
1. apply FindCircuit to $v_i$ to get a circuit $Q$
2. splice $Q$ into $P$ at $v_i$
• continue traversing $P$ (with $Q$ spliced in)

## Eulerian Circuit Pseudocode

  EulerCircuit(V, E, v):
P <- FindCircuit(V, E, v)
for each edge e = (u, w) in P do
if deg(w) > 0 then
Q <- EulerianCircuit(V, E, w)
Splice(P, Q, w)
endif
endfor


## Correctness

Claim. If $G$ is even and connected, then EulerCircuit returns an Eulerian circuit.

Argue by induction on $m =$ number of edges in $G$.

Base Case, $m = 0$. If $G$ is connected and has no edges, then $G$ has only one vertex, so EulerCircuit correctly outputs an Eulerian circuit (of length $0$)

## Inductive Step

Suppose EulerCircuit finds an Eulerian circuit on all connected, even graphs with fewer than $m$ edges. Then:

1. After removing $P$ from $G$, $G$ has fewer than $m$ edges
2. $G$ is still even
3. $G$ may be disconnected, but all components touch $P$
4. By inductive hypothesis, EulerCircuit finds Eulerian circuit in each component
5. Splicing together circuits gives Eulerian circuit for whole graph

## Conclusion

$G$ is Eulerian if and only if $G$ is even and connected.

If $G$ is Eulerian, then an Eulerian circuit can be found by greedily traversing the graph, and recursively finding Eulerian circuits on remaining components.

## More Bridges

Gephyrophobia = fear of bridges

Question. How to get from one landmass to another, crossing the fewest possible?

## Strategy

Find shortest (fewest hops) route by:

1. find all vertices reachable in 1 hop
2. find all vertices reachable in 2 hops
3. find all vertices reachable in 3 hops

Continue until destination is found

## Single Source Shortest Paths (SSSP)

Unweighted version

Input.

• a Graph $G = (V, E)$
• an initial vertex $u \in V$
• each vertex $v \in V$ has associated adjacency list
• list of $v$’s neighbors

Output.

• A map $d: V \to \{-1, 0, 1, 2, \ldots\}$ such that $d(v)$ is length of shortest path (fewest hops) from $u$ to $v$

• $d[v] = -1$ indicates no path from $u$ to $v$

## BFS Solution

1. start at $u$
2. examine $u$’s neighbors, at distance $1$
3. examine $u$’s neighbors’ neighbors, at distance $2$
4. $\vdots$

Greedily examine closest vertices that have not yet been examined…

## Queues

• stores elements
• two basic operations
• enqueue(x) adds element x to queue
• dequeue() removes and returns element
• FIFO: first in, first out

## BFS Pseudocode

  BFS(V, E, u):
intialize d[v] <- -1 for all v
d[u] <- 0
queue.enqueue(u)
while queue is not empty do
v <- queue.dequeue()
for each neighbor w of v do
if d[w] = -1 then
d[w] <- d[v] + 1
queue.enqueue(w)
return d


## BFS Correctness

Theorem. When BFS(V, E, u) terminates, for every vertex $v \in V$, $d[v]$ stores the distance (minimum number of hops) from $u$ to $v$.

Analysis. Break $V$ into layers

• $L_0$ contains only $u$
• $L_1$ contains neighbors of $u$
• $L_2$ contains neighbors of neighbors of $u$
• $\vdots$
• $L_k$ contains vertices not in $L_0, \ldots, L_{k-1}$ but with at least one neighbor in $L_{k-1}$

## Layered Claims

Claim 1. A vertex $v$ is in $L_k$ if and only if the shortest path from $u$ to $v$ has length $k$.

Claim 2. In an execution of BFS the following hold for every $k$:

1. If $v \in L_k$, then $v$ is added to the queue in some iteration
2. when $v$ is added to the queue, $d[v] <- k$
3. $v$ is added to the queue before any vertex $w \in L_\ell$ with $\ell > k$

Proofs: use induction on $k$ (details in text)

Conclusion. BFS correctly computes $d[v]$ for every v.

## Summary

To find shortest paths (fewest hops) from $u$ to all other vertices:

• greedily examine nearest vertices
• added neighbors of nearest vertices to be examined next
• use a queue to store pending vertices

## Next Time

• Weighted graphs
• Priority queues