Download - Graph Algorithms

Transcript
Page 1: Graph Algorithms

Introduction to AlgorithmsCS135

Elementary Graph AlgorithmsProf. Ronald M. Tuñgol

Page 2: Graph Algorithms

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

Page 3: Graph Algorithms

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).

Page 4: Graph Algorithms

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.

Page 5: Graph Algorithms

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.

Page 6: Graph Algorithms

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.

Page 7: Graph Algorithms

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

Page 8: Graph Algorithms

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

Page 9: Graph Algorithms

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

Page 10: Graph Algorithms

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

Page 11: Graph Algorithms

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

Page 12: Graph Algorithms

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

Page 13: Graph Algorithms

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

Page 14: Graph Algorithms

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)

Page 15: Graph Algorithms

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

Page 16: Graph Algorithms

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

Page 17: Graph Algorithms

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

Page 18: Graph Algorithms

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

Page 19: Graph Algorithms

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

Page 20: Graph Algorithms

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

Page 21: Graph Algorithms

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

Page 22: Graph Algorithms

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

Page 23: Graph Algorithms

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

Page 24: Graph Algorithms

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

Page 25: Graph Algorithms

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

Page 26: Graph Algorithms

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

Page 27: Graph Algorithms

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

Page 28: Graph Algorithms

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

Page 29: Graph Algorithms

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)

Page 30: Graph Algorithms

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

Page 31: Graph Algorithms

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

Page 32: Graph Algorithms

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

Page 33: Graph Algorithms

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

Page 34: Graph Algorithms

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:

Page 35: Graph Algorithms

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.


Top Related