Upload
ako-si-toytoy
View
129
Download
1
Tags:
Embed Size (px)
Citation preview
Introduction to AlgorithmsCS135
Elementary Graph AlgorithmsProf. Ronald M. Tuñgol
2/14/02 Introduction to Algorithms CLRS16.2
Graphs
A graph G = (V, E):• V is a finite set of vertices.• E is a set of vertex pairs called edges.
– directed edge (arc): (u, v), u, v ∈ V– undirected edge: u, v, u, v ∈ V, u ≠ v
11 22
55
44
33
11 22
55
44
33
a digraph an undirected graph
2/14/02 Introduction to Algorithms CLRS16.3
Adjacency-list11 22
55
44
33
2 532
3
4
5
143
4
1
Array Adj of |V| lists.• Space requirement is Θ(V + E).• Query (u, v) ∈ E? takes O(E) time.• Suitable for sparse graphs: |E| = o(V2).
2/14/02 Introduction to Algorithms CLRS16.4
Adjacency-matrix11 22
55
44
33
|V| × |V| matrix A.• Space requirement is Θ(V2).• Query (u, v) ∈ E? takes Θ(1) time.• Suitable for dense graphs: |E| = Ω(V2).
010005000014000003
01100210110154321A
A[u, v] =1 ⇔ (u, v) ∈ E.
2/14/02 Introduction to Algorithms CLRS16.5
Breadth-first search
rr ss
vv
uutt
xxww
BFS(G, s) for each vertex u ∈ V[G] – s do state[u] ← “undiscovered” state[s] ← “discovered” Q ← ∅ ENQUEUE(Q, s) while Q ≠ ∅ do u ← DEQUEUE(Q)
for each v ∈ Adj[u] do if state[v] = “undiscovered” then
state[v] ← “discovered” ENQUEUE(Q, v) state[u] ← “completely explored”
• “the closer the earlier”• can be modified to find shortest-paths from a source vertex.Denote by δ(s, v) the shortest-path distancefrom source s to vertex v ∈ V.
2/14/02 Introduction to Algorithms CLRS16.6
Shortest paths with BFS
rr ss
vv
uutt
xxww
BFS(G, s) for each vertex u ∈ V[G] – s do state[u] ← “undiscovered” state[s] ← “discovered” Q ← ∅ ENQUEUE(Q, s) while Q ≠ ∅ do u ← DEQUEUE(Q)
for each v ∈ Adj[u] do if state[v] = “undiscovered” then
state[v] ← “discovered” ENQUEUE(Q, v) state[u] ← “completely explored”
Use arrays d and π to store shortestdistances and predecessors.• Initialize: d[u] ← +∞ for allnonsource vertices u, d[s] ← 0.• As vertex v is discovered fromvertex u, set d[v] ← d[u] + 1.
Theorem. d[v] = δ(s, v) for all v ∈ V upontermination of BFS.
2/14/02 Introduction to Algorithms CLRS16.7
Shortest paths with BFSr:∞r:∞ s:0s:0
v :∞v :∞
u:∞u:∞t:∞t:∞
x:∞x:∞w:∞w:∞
BFS(G, s) for each vertex u ∈ V[G] – s do state[u] ← “undiscovered”
d[u] ← ∞, π[u] ← NIL state[s] ← “discovered” d[s] ← 0, π[s] ← NIL Q ← ∅ ENQUEUE(Q, s) while Q ≠ ∅ do u ← DEQUEUE(Q)
for each v ∈ Adj[u] do if state[v] = “undiscovered” then
state[v] ← “discovered” d[v] ← d[u] + 1, π[v] ← u
ENQUEUE(Q, v) state[u] ← “completely explored”
Q s:0
2/14/02 Introduction to Algorithms CLRS16.8
Shortest paths with BFSr:∞r:∞ s:0s:0
v :1v :1
u:∞u:∞t:1t:1
x:∞x:∞w:∞w:∞
BFS(G, s) for each vertex u ∈ V[G] – s do state[u] ← “undiscovered”
d[u] ← ∞, π[u] ← NIL state[s] ← “discovered” d[s] ← 0, π[s] ← NIL Q ← ∅ ENQUEUE(Q, s) while Q ≠ ∅ do u ← DEQUEUE(Q)
for each v ∈ Adj[u] do if state[v] = “undiscovered” then
state[v] ← “discovered” d[v] ← d[u] + 1, π[v] ← u
ENQUEUE(Q, v) state[u] ← “completely explored”
Q v:1t:1
2/14/02 Introduction to Algorithms CLRS16.9
Shortest paths with BFSr:∞r:∞ s:0s:0
v :1v :1
u:∞u:∞t:1t:1
x:∞x:∞w:2w:2
BFS(G, s) for each vertex u ∈ V[G] – s do state[u] ← “undiscovered”
d[u] ← ∞, π[u] ← NIL state[s] ← “discovered” d[s] ← 0, π[s] ← NIL Q ← ∅ ENQUEUE(Q, s) while Q ≠ ∅ do u ← DEQUEUE(Q)
for each v ∈ Adj[u] do if state[v] = “undiscovered” then
state[v] ← “discovered” d[v] ← d[u] + 1, π[v] ← u
ENQUEUE(Q, v) state[u] ← “completely explored”
Q w:2v:1
2/14/02 Introduction to Algorithms CLRS16.10
Shortest paths with BFSr:2r:2 s:0s:0
v :1v :1
u:∞u:∞t:1t:1
x:∞x:∞w:2w:2
BFS(G, s) for each vertex u ∈ V[G] – s do state[u] ← “undiscovered”
d[u] ← ∞, π[u] ← NIL state[s] ← “discovered” d[s] ← 0, π[s] ← NIL Q ← ∅ ENQUEUE(Q, s) while Q ≠ ∅ do u ← DEQUEUE(Q)
for each v ∈ Adj[u] do if state[v] = “undiscovered” then
state[v] ← “discovered” d[v] ← d[u] + 1, π[v] ← u
ENQUEUE(Q, v) state[u] ← “completely explored”
Q r:2w:2
2/14/02 Introduction to Algorithms CLRS16.11
Shortest paths with BFSr:2r:2 s:0s:0
v :1v :1
u:3u:3t:1t:1
x:3x:3w:2w:2
BFS(G, s) for each vertex u ∈ V[G] – s do state[u] ← “undiscovered”
d[u] ← ∞, π[u] ← NIL state[s] ← “discovered” d[s] ← 0, π[s] ← NIL Q ← ∅ ENQUEUE(Q, s) while Q ≠ ∅ do u ← DEQUEUE(Q)
for each v ∈ Adj[u] do if state[v] = “undiscovered” then
state[v] ← “discovered” d[v] ← d[u] + 1, π[v] ← u
ENQUEUE(Q, v) state[u] ← “completely explored”
Q u:3r:2 x:3
2/14/02 Introduction to Algorithms CLRS16.12
Shortest paths with BFSr:2r:2 s:0s:0
v :1v :1
u:3u:3t:1t:1
x:3x:3w:2w:2
BFS(G, s) for each vertex u ∈ V[G] – s do state[u] ← “undiscovered”
d[u] ← ∞, π[u] ← NIL state[s] ← “discovered” d[s] ← 0, π[s] ← NIL Q ← ∅ ENQUEUE(Q, s) while Q ≠ ∅ do u ← DEQUEUE(Q)
for each v ∈ Adj[u] do if state[v] = “undiscovered” then
state[v] ← “discovered” d[v] ← d[u] + 1, π[v] ← u
ENQUEUE(Q, v) state[u] ← “completely explored”
Q x:3u:3
2/14/02 Introduction to Algorithms CLRS16.13
Shortest paths with BFSr:2r:2 s:0s:0
v :1v :1
u:3u:3t:1t:1
x:3x:3w:2w:2
BFS(G, s) for each vertex u ∈ V[G] – s do state[u] ← “undiscovered”
d[u] ← ∞, π[u] ← NIL state[s] ← “discovered” d[s] ← 0, π[s] ← NIL Q ← ∅ ENQUEUE(Q, s) while Q ≠ ∅ do u ← DEQUEUE(Q)
for each v ∈ Adj[u] do if state[v] = “undiscovered” then
state[v] ← “discovered” d[v] ← d[u] + 1, π[v] ← u
ENQUEUE(Q, v) state[u] ← “completely explored”
Q x:3
2/14/02 Introduction to Algorithms CLRS16.14
Shortest paths with BFSr:2r:2 s:0s:0
v :1v :1
u:3u:3t:1t:1
x:3x:3w:2w:2
BFS(G, s) for each vertex u ∈ V[G] – s do state[u] ← “undiscovered”
d[u] ← ∞, π[u] ← NIL state[s] ← “discovered” d[s] ← 0, π[s] ← NIL Q ← ∅ ENQUEUE(Q, s) while Q ≠ ∅ do u ← DEQUEUE(Q)
for each v ∈ Adj[u] do if state[v] = “undiscovered” then
state[v] ← “discovered” d[v] ← d[u] + 1, π[v] ← u
ENQUEUE(Q, v) state[u] ← “completely explored”
Q ∅Breadth-first search treeGπ = (Vπ, Eπ) where• Vπ = v∈ V: π[v] ≠ NIL ∪ s• Eπ = (π[v], v): v∈ Vπ −sRunning time: O(V + E)
2/14/02 Introduction to Algorithms CLRS16.15
Depth-first search
rr ss
vv
uutt
xxww
DFS(G) for each vertex u ∈ V[G] do state[u] ← “undiscovered”
π[u] ← NIL time ← 0 for each vertex u ∈ V[G] do if state[u] = “undiscovered” then DFS-VISIT(u)
DFS-VISIT(u) state[u] ← “discovered” d[u] ← time ← time + 1 for each v ∈ Adj[u] do
if state[v] = “undiscovered” then π[v] ← u DFS-VISIT(v) state[u] ← “completely explored” f[u] ← time ← time + 1
• search deeper, backtrack when stuck• produces a DFS forest• makes recursive callsto DFS-VISIT
2/14/02 Introduction to Algorithms CLRS16.16
Depth-first search
r:1/ r:1/ ss
vv
uutt
xxww
DFS(G) for each vertex u ∈ V[G] do state[u] ← “undiscovered”
π[u] ← NIL time ← 0 for each vertex u ∈ V[G] do if state[u] = “undiscovered” then DFS-VISIT(u)
DFS-VISIT(u) state[u] ← “discovered” d[u] ← time ← time + 1 for each v ∈ Adj[u] do
if state[v] = “undiscovered” then π[v] ← u DFS-VISIT(v) state[u] ← “completely explored” f[u] ← time ← time + 1
For each node u,compute• d[u]: time of first visit• f[u]: time when alladjacent nodes havebeen visited
2/14/02 Introduction to Algorithms CLRS16.17
Depth-first search
r:1/ r:1/ ss
v:2/v:2/
uutt
xxww
DFS(G) for each vertex u ∈ V[G] do state[u] ← “undiscovered”
π[u] ← NIL time ← 0 for each vertex u ∈ V[G] do if state[u] = “undiscovered” then DFS-VISIT(u)
DFS-VISIT(u) state[u] ← “discovered” d[u] ← time ← time + 1 for each v ∈ Adj[u] do
if state[v] = “undiscovered” then π[v] ← u DFS-VISIT(v) state[u] ← “completely explored” f[u] ← time ← time + 1
2/14/02 Introduction to Algorithms CLRS16.18
Depth-first search
r:1/ r:1/ s:3/s:3/
v:2/v:2/
uutt
xxww
DFS(G) for each vertex u ∈ V[G] do state[u] ← “undiscovered”
π[u] ← NIL time ← 0 for each vertex u ∈ V[G] do if state[u] = “undiscovered” then DFS-VISIT(u)
DFS-VISIT(u) state[u] ← “discovered” d[u] ← time ← time + 1 for each v ∈ Adj[u] do
if state[v] = “undiscovered” then π[v] ← u DFS-VISIT(v) state[u] ← “completely explored” f[u] ← time ← time + 1
2/14/02 Introduction to Algorithms CLRS16.19
Depth-first search
r:1/ r:1/ s:3/s:3/
v:2/v:2/
uut:4/t:4/
xxww
DFS(G) for each vertex u ∈ V[G] do state[u] ← “undiscovered”
π[u] ← NIL time ← 0 for each vertex u ∈ V[G] do if state[u] = “undiscovered” then DFS-VISIT(u)
DFS-VISIT(u) state[u] ← “discovered” d[u] ← time ← time + 1 for each v ∈ Adj[u] do
if state[v] = “undiscovered” then π[v] ← u DFS-VISIT(v) state[u] ← “completely explored” f[u] ← time ← time + 1
2/14/02 Introduction to Algorithms CLRS16.20
Depth-first search
r:1/ r:1/ s:3/s:3/
v:2/v:2/
uut:4/5t:4/5
xxww
DFS(G) for each vertex u ∈ V[G] do state[u] ← “undiscovered”
π[u] ← NIL time ← 0 for each vertex u ∈ V[G] do if state[u] = “undiscovered” then DFS-VISIT(u)
DFS-VISIT(u) state[u] ← “discovered” d[u] ← time ← time + 1 for each v ∈ Adj[u] do
if state[v] = “undiscovered” then π[v] ← u DFS-VISIT(v) state[u] ← “completely explored” f[u] ← time ← time + 1
2/14/02 Introduction to Algorithms CLRS16.21
Depth-first search
r:1/ r:1/ s:3/6s:3/6
v:2/v:2/
uut:4/5t:4/5
xxww
DFS(G) for each vertex u ∈ V[G] do state[u] ← “undiscovered”
π[u] ← NIL time ← 0 for each vertex u ∈ V[G] do if state[u] = “undiscovered” then DFS-VISIT(u)
DFS-VISIT(u) state[u] ← “discovered” d[u] ← time ← time + 1 for each v ∈ Adj[u] do
if state[v] = “undiscovered” then π[v] ← u DFS-VISIT(v) state[u] ← “completely explored” f[u] ← time ← time + 1
2/14/02 Introduction to Algorithms CLRS16.22
Depth-first search
r:1/ r:1/ s:3/6s:3/6
v:2/v:2/
uut:4/5t:4/5
xxw:7/w:7/
DFS(G) for each vertex u ∈ V[G] do state[u] ← “undiscovered”
π[u] ← NIL time ← 0 for each vertex u ∈ V[G] do if state[u] = “undiscovered” then DFS-VISIT(u)
DFS-VISIT(u) state[u] ← “discovered” d[u] ← time ← time + 1 for each v ∈ Adj[u] do
if state[v] = “undiscovered” then π[v] ← u DFS-VISIT(v) state[u] ← “completely explored” f[u] ← time ← time + 1
2/14/02 Introduction to Algorithms CLRS16.23
Depth-first search
r:1/ r:1/ s:3/6s:3/6
v:2/v:2/
uut:4/5t:4/5
xxw:7/8w:7/8
DFS(G) for each vertex u ∈ V[G] do state[u] ← “undiscovered”
π[u] ← NIL time ← 0 for each vertex u ∈ V[G] do if state[u] = “undiscovered” then DFS-VISIT(u)
DFS-VISIT(u) state[u] ← “discovered” d[u] ← time ← time + 1 for each v ∈ Adj[u] do
if state[v] = “undiscovered” then π[v] ← u DFS-VISIT(v) state[u] ← “completely explored” f[u] ← time ← time + 1
2/14/02 Introduction to Algorithms CLRS16.24
Depth-first search
r:1/ r:1/ s:3/6s:3/6
v:2/9v:2/9
uut:4/5t:4/5
xxw:7/8w:7/8
DFS(G) for each vertex u ∈ V[G] do state[u] ← “undiscovered”
π[u] ← NIL time ← 0 for each vertex u ∈ V[G] do if state[u] = “undiscovered” then DFS-VISIT(u)
DFS-VISIT(u) state[u] ← “discovered” d[u] ← time ← time + 1 for each v ∈ Adj[u] do
if state[v] = “undiscovered” then π[v] ← u DFS-VISIT(v) state[u] ← “completely explored” f[u] ← time ← time + 1
2/14/02 Introduction to Algorithms CLRS16.25
Depth-first search
r:1/10 r:1/10 s:3/6s:3/6
v:2/9v:2/9
uut:4/5t:4/5
xxw:7/8w:7/8
DFS(G) for each vertex u ∈ V[G] do state[u] ← “undiscovered”
π[u] ← NIL time ← 0 for each vertex u ∈ V[G] do if state[u] = “undiscovered” then DFS-VISIT(u)
DFS-VISIT(u) state[u] ← “discovered” d[u] ← time ← time + 1 for each v ∈ Adj[u] do
if state[v] = “undiscovered” then π[v] ← u DFS-VISIT(v) state[u] ← “completely explored” f[u] ← time ← time + 1
2/14/02 Introduction to Algorithms CLRS16.26
Depth-first search
r:1/10 r:1/10 s:3/6s:3/6
v:2/9v:2/9
u:11/u:11/t:4/5t:4/5
xxw:7/8w:7/8
DFS(G) for each vertex u ∈ V[G] do state[u] ← “undiscovered”
π[u] ← NIL time ← 0 for each vertex u ∈ V[G] do if state[u] = “undiscovered” then DFS-VISIT(u)
DFS-VISIT(u) state[u] ← “discovered” d[u] ← time ← time + 1 for each v ∈ Adj[u] do
if state[v] = “undiscovered” then π[v] ← u DFS-VISIT(v) state[u] ← “completely explored” f[u] ← time ← time + 1
2/14/02 Introduction to Algorithms CLRS16.27
Depth-first search
r:1/10 r:1/10 s:3/6s:3/6
v:2/9v:2/9
u:11/u:11/t:4/5t:4/5
x:12/x:12/w:7/8w:7/8
DFS(G) for each vertex u ∈ V[G] do state[u] ← “undiscovered”
π[u] ← NIL time ← 0 for each vertex u ∈ V[G] do if state[u] = “undiscovered” then DFS-VISIT(u)
DFS-VISIT(u) state[u] ← “discovered” d[u] ← time ← time + 1 for each v ∈ Adj[u] do
if state[v] = “undiscovered” then π[v] ← u DFS-VISIT(v) state[u] ← “completely explored” f[u] ← time ← time + 1
2/14/02 Introduction to Algorithms CLRS16.28
Depth-first search
r:1/10 r:1/10 s:3/6s:3/6
v:2/9v:2/9
u:11/u:11/t:4/5t:4/5
x:12/13x:12/13w:7/8w:7/8
DFS(G) for each vertex u ∈ V[G] do state[u] ← “undiscovered”
π[u] ← NIL time ← 0 for each vertex u ∈ V[G] do if state[u] = “undiscovered” then DFS-VISIT(u)
DFS-VISIT(u) state[u] ← “discovered” d[u] ← time ← time + 1 for each v ∈ Adj[u] do
if state[v] = “undiscovered” then π[v] ← u DFS-VISIT(v) state[u] ← “completely explored” f[u] ← time ← time + 1
2/14/02 Introduction to Algorithms CLRS16.29
Depth-first search
r:1/10 r:1/10 s:3/6s:3/6
v:2/9v:2/9
u:11/14u:11/14t:4/5t:4/5
x:12/13x:12/13w:7/8w:7/8
Classification of edges• tree edges: those on the DFS forest• back edges: those that connect descendants toancestors (self-loops, too)• forward edges: non-tree edges connectingancestors to descendants• cross edges: all other edges
Running time: Θ(V + E)
2/14/02 Introduction to Algorithms CLRS16.30
Depth-first search
r:1/10 r:1/10 s:3/6s:3/6
v:2/9v:2/9
u:11/14u:11/14t:4/5t:4/5
x:12/13x:12/13w:7/8w:7/8
Theorem.(Parenthesis structure)Let I[u] = [d[u], f[u]].Then either I[u] andI[v] are disjoint or oneis entirely containedwithin the other.
1 2 3 4 5 6 7 8 9 10 11 12 13 14(r (v (s (t t) s) (w w) v) r) (u (x x) u)
rv
st
ux
w
2/14/02 Introduction to Algorithms CLRS16.31
Topological sort
uu vv
xx
ww
zzyy
A topological sort of a dag G = (V, E) is alinear ordering of V such that if (u, v) ∈ Ethen u v.Lemma. A directed graph is acyclic if andonly if a depth-first search of G yields noback edges.
TOPOLOGICAL-SORT(G) call DFS(G) to compute the finishing times f[v] for each vertex v as each vertex is finished, insert it onto the front of a linked list return the linked list of vertices
2/14/02 Introduction to Algorithms CLRS16.32
Topological sortu:1/12u:1/12 v:2/11v:2/11
x:6/7x:6/7
w:3/4w:3/4
z:8/9z:8/9y:5/10y:5/10
uu vv xx wwzzyy
Topological sort: u v y z x wRunning time: Θ(V + E)
TOPOLOGICAL-SORT(G) call DFS(G) to compute the finishing times f[v] for each vertex v as each vertex is finished, insert it onto the front of a linked list return the linked list of vertices
2/14/02 Introduction to Algorithms CLRS16.33
Strongly connectedcomponents
Given a digraph G = (V, E).Write u v if there is a path from u to v in G.
A strongly connected component of G is amaximal set of vertices C ⊆ V such that forevery pair u, v ∈ V, both u v and v u, thatis, u and v are reachable from each other.
aa bb
gg
ddcc
jjiihh
ee
kk
ff
ll
2/14/02 Introduction to Algorithms CLRS16.34
Strongly connectedcomponents
STRONGLY-CONNECTED-COMPONENTS(G) call DFS(G) to compute the finishing times f[u] for each vertex u compute GT
call DFS(GT), but in the main loop of DFS, consider the vertices in order of decreasing f[u] output the vertices of each tree in the DFS forest as a separate strongly connected component
a:1/24a:1/24 b:2/21b:2/21
g:22/23g:22/23
d:6/17d:6/17c:5/18c:5/18
j:13/14j:13/14i:4/19i:4/19h:3/20h:3/20
e:7/16e:7/16
k:12/15k:12/15
f:8/11f:8/11
l:9/10l:9/10
A Θ(V + E) algorithm:
2/14/02 Introduction to Algorithms CLRS16.35
Strongly connectedcomponents
a:1/2a:1/2 b:5/12b:5/12
g:3/4g:3/4
d:13/20d:13/20c:6/11c:6/11
j:14/19j:14/19i:7/10i:7/10h:8/9h:8/9
e:16/17e:16/17
k:15/18k:15/18
f:21/22f:21/22
l:23/24l:23/24
The transpose graph and its DFS trees:
The strongly connected components are therefore a, g, b, c, h, i, d, e, j, k, f, l.