Graph Algorithms
Graph Algorithms
Graph Algorithms
References:
Algorithms, Jeff Erickson, Chapter 5 Basic Graph Algorithms,
Chapter 6, Depth-First Search
Algorithm Desgin Manual, Chapter 5.
Language of Graph 2/15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
(V ; E )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Adjacency list:
Here the list of neighbors for each vertex is stored in a linked list;
but it does not have to be linked list;
A dynamic array (vector), binary search tree, or hash table could
also be used. Different data structures have different performance
characteristics.
Adjacency matrix: a V V matrix A of 0s and 1s:
For undirected graph, A[u; v] = 1 iff uv 2 E
For directed graph, A[u; v] = 1 iff u ! v 2 E
The adjacency matrix for undirected graph is symmetric, and the
diagonal is always 0. For directed graph it's not necessarily sym-
metric, and the diagonal could be non-zero.
Comparison:
We always assume adj list with linked list as the graph represen-
tation, unless explicitly stated otherwise.
Whatever-First Search 5/15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Note that the modified version does exactly the same thing as before,
but additionally records parent node (who put me in the bag the
first time?) along the way. This parent relationship helps us under-
stand and prove the claim that the search algorithm indeed visits
all reachable nodes at least once.
Lemma. WhateverFirstSearch(s) marks every vertex reachable
from s and only those vertices. Moreover, the set of all pairs (v ;
parent(v)) with parent(v) =
/ ; defines a spanning tree of the com-
ponent containing s.
Sketch proof:
First, we argue that the algorithm marks every reachable vertex
v from s.
Prove by induction on the shortest-path length from s to vertex
v.
Second, we argue that the pairs (v,parent(v)) forms a spanning
tree of the component containing s.
Claim: for every vertex v, the parent path: v ! parent(v) !
parent(parent(v)) ! ! eventually leads to s.
Claim: all the parent edges form a tree
Analysis. The running time of the whatever-first-search depends
on what data structures we use for the bag, but we can make a
few general observations.
Suppose putting a node into the bag or getting one out takes T
time.
The (neighbor-loop) is executed exactly once for each marked
vertex v, and therefore at most V times.
Each edge uv in the component is put into bag exactly twice;
once as (u; v) and once as (v ; u). So the (put-in) statement is
executed at most 2E times.
For the (take-out) statement, we can't take more out than we
put in, so it's executed at most 2E times.
So, WhateverFirstSearch() takes O (V + E T ) time. (If graph is
represented as adj matrix then it's O(V 2 + ET ). Why?
Important Variants:
Stack: Depth-First
Queue: Breadth-First
Priority-queue: Best-First
Flood Fill 6/15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
A Concrete Data Structure for Graph 7/15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
DFSAll(G): DFSAll(G):
Preprocess(G) Preprocess(G)
for all vertices v add vertex s
unmark v for all vertices v
for all vertices v add edge s ! v
if v is unmarked unmark v
DFS(v) DFS(s)
Preorder and Postorder
Note: this is for directed graph. Undirected graph DFS tree does
not have forward edge or cross-edge! It's very powerful precisely
because it classifies edges into two classes: tree/back edges.
Question: why no forward/cross edges in undirected DFS?
Detecting Cycles 9/15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Memoization and Dynamic Programming 12/15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Why?
(why?)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15