
















































Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
Key points of this note are: Graphs, Traversal, Breadth First, Search, Generic, Trace, Structure.
Typology: Study notes
1 / 56
This page cannot be seen from the preview
Don't miss anything!

















































Chapter 8
Graphs
We begin a major new topic: Graphs. Graphs are important discrete structures because they are a flexible mathematical model for many application problems. Any time there is a set of objects and there is some sort of “connection” or “relationship” or “interaction” between pairs of objects, a graph is a good way to model this. Examples of this can be found in computer and communication networks transportation networks, e.g., roads VLSI, logic circuits surface meshes for shape description in computer-aided design and GIS precedence constraints in scheduling systems.
A graph G = (V, E) consists of a finite set of vertices V (or nodes) and E, a binary relation on V called edges. E is a set of pairs from V. If a pair is ordered , we have a directed graph. For unordered pair, we have an undirected graph.
graph
multi graph
directed graph (digraph)
digraph
self-loop
Figure 8.1: Types of graphs
A vertex w is adjacent to vertex v if there is an edge from v to w.
1 3
2 4
in: 1 out: 3
in: 1 out: 1
in: 1 out: 2
in: 3 out: 0
Figure 8.4: In and out degrees of vertices of a graph
For a digraph G = (V, E),
∑
v∈V
in-degree (v) =
v∈V
out-degree (v) = |E|
where |E| means the cardinality of the set E, i.e., the number of edges.
For an undirected graph G = (V, E),
∑
v∈V
degree (v) = 2 |E|
where |E| means the cardinality of the set E, i.e., the number of edges.
A path in a directed graphs is a sequence of vertices 〈v 0 , v 1 ,... , vk〉 such that (vi− 1 , vi) is an edge for i = 1, 2,... , k. The length of the paths is the number of edges, k. A vertex w is reachable from vertex u is there is a path from u to w. A path is simple if all vertices (except possibly the fist and last) are distinct.
A cycle in a digraph is a path containing at least one edge and for which v 0 = vk. A Hamiltonian cycle is a cycle that visits every vertex in a graph exactly once. A Eulerian cycle is a cycle that visits every edge of the graph exactly once. There are also “path” versions in which you do not need return to the starting vertex.
Figure 8.5: Cycles in a directed graph
A graph is said to be acyclic if it contains no cycles. A graph is connected if every vertex can reach every other vertex. A directed graph that is acyclic is called a directed acyclic graph (DAG).
There are two ways of representing graphs: using an adjacency matrix and using an adjacency list. Let G = (V, E) be a digraph with n = |V| and let e = |E|. We will assume that the vertices of G are indexed {1, 2,... , n}.
An adjacency matrix is a n × n matrix defined for 1 ≤ v, w ≤ n.
A[v, w] =
1 if (v, w) ∈ E 0 otherwise
An adjacency list is an array Adj[1..n] of pointers where for 1 ≤ v ≤ n, Adj[v] points to a linked list containing the vertices which are adjacent to v
Adjacency matrix requires Θ(n^2 ) storage and adjacency list requires Θ(n + e) storage.
0
1 2 3 1
2
3
1 1 1
1
1
0
0 0
Adjacency Matrix
1 2 3
3
2
1
2
3
Adj
Adjacency List
Figure 8.6: Graph Representations
8.1 Graph Traversal
To motivate our first algorithm on graphs, consider the following problem. We are given an undirected graph G = (V, E) and a source vertex s ∈ V. The length of a path in a graph is the number of edges on
Figure 8.8: Source vertex for breadth-first-search (BFS)
Figure 8.9: Wave reaching distance 1 vertices during BFS
Figure 8.10: Wave reaching distance 2 vertices during BFS
s
Figure 8.11: Wave reaching distance 3 vertices during BFS
Breadth-first search is one instance of a general family of graph traversal algorithms. Traversing a graph means visiting every node in the graph. Another traversal strategy is depth-first search (DFS). DFS procedure can be written recursively or non-recursively. Both versions are passed s initially.
RECURSIVEDFS(v) 1 if (v is unmarked ) 2 then mark v 3 for each edge (v, w) 4 do RECURSIVEDFS(w)
ITERATIVEDFS(s) 1 PUSH(s) 2 while stack not empty 3 do v ← POP() 4 if v is unmarked 5 then mark v 6 for each edge (v, w) 7 do PUSH(w)
The generic graph traversal algorithm stores a set of candidate edges in some data structures we’ll call a “ bag ”. The only important properties of the “bag” are that we can put stuff into it and then later take stuff
Figure 8.12: Trace of Depth-first-search algorithm: source vertex ‘s’
Figure 8.13: Trace of DFS algorithm: vertex ‘a’ popped
Figure 8.14: Trace of DFS algorithm: vertex ‘c’ popped
Figure 8.15: Trace of DFS algorithm: vertex ‘f’ popped
Figure 8.16: Trace of DFS algorithm: vertex ‘g’ popped
Figure 8.19: Trace of DFS algorithm: vertex ‘d’ popped
a
b
c (^) f
e
d g
s
BFS Tree
Figure 8.20: Trace of DFS algorithm: the final DFS tree
Each execution of line 3 or line 8 in the TRAVERSE-DFS algorithm takes constant time. So the overall running time is O(V + E). Since the graph is connected, V ≤ E + 1 , this is O(E).
If we implement the bag by using a queue , we have breadth-first search (BFS). Each execution of line 3
or line 8 still takes constant time. So overall running time is still O(E).
TRAVERSE(s) 1 enqueue(∅, s) 2 while queue not empty 3 do dequeue(p, v) 4 if (v is unmarked ) 5 then mark v 6 parent (v) ← p 7 for each edge (v, w) 8 do enqueue(v, w)
If the graph is represented using an adjacency matrix , the finding of all the neighbors of vertex in line 7 takes O(V) time. Thus depth-first and breadth-first take O(V^2 ) time overall.
Either DFS or BFS yields a spanning tree of the graph. The tree visits every vertex in the graph. This fact is established by the following lemma:
Lemma:
The generic TRAVERSE(S) marks every vertex in any connected graph exactly once and the set of edges (v, parent(v)) with parent(v) 6 = ∅ form a spanning tree of the graph.
Proof:
First, it should be obvious that no vertex is marked more than once. Clearly, the algorithm marks s. Let v 6 = s be a vertex and let s → · · · → u → v be a path from s to v with the minimum number of edges.
Since the graph is connected, such a path always exists. If the algorithm marks u, then it must put (u, v) into the bag, so it must take (u, v) out of the bag at which point v must be marked. Thus, by induction on the shortest-path distance from s, the algorithm marks every vertex in the graph.
Call an edge (v, parent(v)) with parent(v) 6 = ∅, a parent edge. For any node v, the path of parent edges v → parent(v) → parent(parent(v)) →... eventually leads back to s. So the set of parent edges form a connected graph.
Clearly, both end points of every parent edge are marked, and the number of edges is exactly one less than the number of vertices. Thus, the parent edges form a spanning tree.
As we traverse the graph in DFS order, we will associate two numbers with each vertex. When we first discover a vertex u, store a counter in d[u]. When we are finished processing a vertex, we store a counter in f[u]. These two numbers are time stamps.
Consider the recursive version of depth-first traversal
return c return b
b a
c
2/.. 1/..
3/..
b a
c
2/5 1/..
3/
Figure 8.22: DFS with time stamps: processing of ‘b’ and ‘c’ completed
Figure 8.23: DFS with time stamps: recursive processing of ‘f’ and ‘g’
Figure 8.24: DFS with time stamps: processing of ‘f’ and ‘g’ completed
f
g
b a
c
2/5 1/
3/4 7/
6/
d e 11/14 12/
DFS(d) DFS(e) return e return f
Figure 8.25: DFS with time stamps: processing of ‘d’ and ‘e’
Notice that the DFS tree structure (actually a collection of trees, or a forest) on the structure of the graph is just the recursion tree, where the edge (u, v) arises when processing vertex u we call DFSVISIT(V) for some neighbor v. For directed graphs the edges that are not part of the tree (indicated as dashed edges in Figures 8.21 through 8.25) edges of the graph can be classified as follows:
Back edge: (u, v) where v is an ancestor of u in the tree.
f
g
b a
c
2/5 1/
3/4 7/
6/
d e
11/14 12/
F
C
C C
B
Figure 8.27: Classfication of non-tree edges in the DFS tree for a graph
For undirected graphs, there is no distinction between forward and back edges. By convention they are all called back edges. Furthermore, there are no cross edges (can you see why not?)
The time stamps given by DFS allow us to determine a number of things about a graph or digraph. For example, we can determine whether the graph contains any cycles. We do this with the help of the following two lemmas.
Lemma: Given a digraph G = (V, E), consider any DFS forest of G and consider any edge (u, v) ∈ E. If this edge is a tree, forward or cross edge, then f[u] > f[v]. If this edge is a back edge, then f[u] ≤ f[v].
Proof: For the non-tree forward and back edges the proof follows directly from the parenthesis lemma. For example, for a forward edge (u, v), v is a descendent of u and so v’s start-finish interval is contained within u’s implying that v has an earlier finish time. For a cross edge (u, v) we know that the two time intervals are disjoint. When we were processing u, v was not white (otherwise (u, v) would be a tree edge), implying that v was started before u. Because the intervals are disjoint, v must have also finished before u.
Lemma: Consider a digraph G = (V, E) and any DFS forest for G. G has a cycle if and only if the DFS forest has a back edge.
Proof: If there is a back edge (u, v) then v is an ancestor of u and by following tree edge from v to u, we get a cycle.
We show the contrapositive: suppose there are no back edges. By the lemma above, each of the remaining types of edges, tree, forward, and cross all have the property that they go from vertices with higher finishing time to vertices with lower finishing time. Thus along any path, finish times decrease monotonically, implying there can be no cycle.
The DFS forest in Figure 8.27 has a back edge from vertex ‘g’ to vertex ‘a’. The cycle is ‘a-g-f’.
Beware : No back edges means no cycles. But you should not infer that there is some simple relationship between the number of back edges and the number of cycles. For example, a DFS tree may only have a single back edge, and there may anywhere from one up to an exponential number of simple cycles in the graph.
A similar theorem applies to undirected graphs, and is not hard to prove.
8.2 Precedence Constraint Graph
A directed acyclic graph (DAG) arise in many applications where there are precedence or ordering constraints. There are a series of tasks to be performed and certain tasks must precede other tasks. For example, in construction, you have to build the first floor before the second floor but you can do electrical work while doors and windows are being installed. In general, a precedence constraint graph is a DAG in which vertices are tasks and the edge (u, v) means that task u must be completed before task v begins.
For example, consider the sequence followed when one wants to dress up in a suit. One possible order and its DAG are shown in Figure 8.28. Figure 8.29 shows the DFS with time stamps of the DAG.