d esign & a nalysis of a lgorithm 04 – g raph a lgorithms informatics department parahyangan...
TRANSCRIPT
DESIGN & ANALYSIS OF ALGORITHM04 – GRAPH ALGORITHMS
Informatics Department
Parahyangan Catholic University
MOTIVATION
We have studied how to model and simplify real life problems into graphs
In this course topic, we will further discuss how to represent a graph in a computer program and implements some fundamental graph algorithms Adjacency Matrix representation Adjacency List representation DFS & BFS Traversal Dijkstra’s shortest path (later) Minimum Spanning Tree (later)
In term of programming, a vertex usually carries extra information, thus it is sometimes called a node
GRAPH REPRESENTATIONADJACENCY MATRIX
An adjacency matrix representation of a graph is a n-by-n matrix of Boolean values, with the entry in row v and column w defined to be 1 if there is an edge connecting vertex v and vertex w in the graph, and 0 otherwise.
Example:
13
24
65
1 2 3 4 5 6
1 0 1 0 0 0 0
2 1 0 1 1 0 1
3 0 1 0 1 0 0
4 0 1 1 0 1 0
5 0 0 0 1 0 1
6 0 1 0 0 1 0
When the graph is directed, row v column w is defined to be 1 if there is an edge from v to w
Example:
GRAPH REPRESENTATIONADJACENCY MATRIX
13
24
65
1 2 3 4 5 6
1 0 1 0 0 0 0
2 0 0 0 0 0 1
3 0 1 0 1 0 0
4 0 1 0 0 1 0
5 0 0 0 0 0 1
6 0 0 0 0 0 0
GRAPH REPRESENTATIONADJACENCY MATRIX
If we need to label the edges, we can use integer values instead of Booleans
Example: relationship graph
1 2 3 4 5 6
1 0 1 0 0 0 0
2 1 0 2 4 0 7
3 0 2 0 3 0 0
4 0 4 3 0 5 0
5 0 0 0 5 0 6
6 0 7 0 0 6 0
(1)Ann(3)Tom
(2)Bob
(4)Lea
(6)Noah (5)Jim(6)close friend
(1)sp
ouse
(4)co-worker
(3)love
r(2)b
uddy
(5)f
am
ily
(7)a
cquain
tance
1 Ann
2 Bob
3 Tom
4 Lea
5 Jim
6 Noah
1 spouse
2 buddy
3 lover
4 co-worker
5 family
6 close friend
7 acquaintance
vertices edges
matrix
GRAPH REPRESENTATIONADJACENCY LIST
Adjacency matrix representation is easy to implement with arrays, however, when the graph is sparse (has few edges), it wastes a lot of memory space.
Adjacency list tries to answer this problem. Edges’ information are stored in an array of linked list.
GRAPH REPRESENTATIONADJACENCY LIST :: EXAMPLE
13
24
65
1
2
3
4
5
6
2
3 1 4
2 4
3 2 5
4 6
2 5
6
13
24
65
1
2
3
4
5
6
2
6
2 4
2 5
6
We can add vertex’s and edge’s information to the linked list’s node
(1)Ann(3)Tom
(2)Bob
(4)Lea
(6)Noah (5)Jim(6)close friend
(1)sp
ouse
(4)co-worker
(3)love
r(2)b
uddy
(5)f
am
ily
(7)a
cquain
tance
GRAPH REPRESENTATIONADJACENCY LIST :: EXAMPLE
1 Ann
2 Bob
3 Tom
4 Lea
5 Jim
6 Noah
2 spouse
6 acquaintance
2 buddy 4 lover
5 family 2 co-worker
6close-friend
DFS ALGORITHM
We have discussed DFS traversal in a tree or graph. This traversal method can be easily implemented recursively: To visit a vertex, we mark it as having been visited, then (recursively) visit all the vertices that are adjacent to it and that have not yet been marked
To mark which vertex has been visited, we can use a Boolean array, initially set to 0
DFS ALGORITHM
DFS(G)initialize isVisited[0..n] to falsefor each unvisited vertex v of G
DFS_RECURSIVE(v)
DFS_RECURSIVE(x)isVisited[x] = trueprocess(x)for each unvisited vertex v adjacent to x
DFS_RECURSIVE(v)
Simple DFS Algorithm
DFS ALGORITHM
Sometimes we need to know the order of vertex visited Use an array of n integer to store the order of vertex
visited, instead of array of Boolean isVisited. The array is initially set to 0 (unvisited).
Sometimes we also need to store the traversal tree Use an array of n integer to store the parent’s index
of each vertex (remember, each vertex of a tree has exactly one parent, except the root).
The array is initially set to 0. The vertex (or vertices) which parent remains 0 is the root of the traversal tree (or forest if the graph is disconnected).
DFS ALGORITHM
// global variable ctr = 1
DFS(G)initialize ord[0..n] to 0initialize parent[0..n] to 0for each unvisited vertex v of G
DFS_RECURSIVE(v)
DFS_RECURSIVE(x)ord[x] = ctrctr = ctr+1process(x)for each unvisited vertex v adjacent to x
parent[v] = xDFS_RECURSIVE(v)
DFS Algorithm with ord and parent array
DFS TREE
D
E
B
F G
C
I
A
H
D
E
B
F G
C
I
A
HD
EB
F
G
C
I
A
H
DFS Tree
Recall…
DFS TREE PROPERTIES
During DFS traversal on vertex v, we know a vertex u adjacent to v is already visited iff ord[u] is not 0.
In fact, we can further examine : If ord[u] < ord[v],
then v is u’s ancestor, because v is visited before u If ord[u] > ord[v],
then v is u’s descendant, because v is visited after u If parent[u] is v,
then v is u’s ancestor and also a direct parent of u
Based on these observation, we can “upgrade” our DFS Tree to show more information
DFS TREE
D
E
B
F G
C
I
A
H
D
E
B
F G
C
I
A
HD
E B
F
G
C
I
A
H
DFS Tree
1
2
3
4
5
6 A
7
8
9
B
A
H
F
E
F
I
B
C
G
G
B F
= parent
= down edge
DO
WN
= back edge
BA
CK
DFS TREE
D
E
B
F G
C
I
A
H
D
E
B
F G
C
I
A
H
A B C D E F G H Iparent 0 F B E F I C A Hord 1 7 8 6 5 4 9 2 3
D
E B
F
G
C
I
A
H
DFS Tree
A
1
2
3
4
5
6
7
8
9
B
A
H
F
E
F
I
B
C
G
G
B F
#back edge = #down edge = #chord= #edges that form circuits
EXERCISE
Draw the DFS traversal tree and fill the ord & parent array for this graph !
D
E
B
F
G
C
I
A
H
JK
DFS ALGORITHM
Simple to implement using recursive
The base of many useful algorithm, such as Counting component(s) in a graph Connectivity Flood-fill Topological sort Finding bridge Finding articulation point Etc.
DFS ALGORITHMCOUNTING COMPONENT(S)
CountComponent(G)component = 0for each unvisited vertex v of G
component = component + 1DFS_RECURSIVE(v)
return component
Same as counting how many trees in DFS forest
DFS ALGORITHMCONNECTIVITY
isConnected(G)component = 0for each unvisited vertex v of G
component = component + 1DFS_RECURSIVE(v)
return (component == 1)
Returns true if graph G is connected, returns false otherwise
If #component > 1, then graph must be disconnected
“Flooding” a component that contains vertex v
Same as performing DFS on a single tree only
Sometimes we’re interested to know which vertex (or vertices) are flooded, in such case, we can return the ord array
DFS ALGORITHMFLOOD FILL
FloodFill(v)DFS_RECURSIVE(v)return ord
PROBLEMSCHEDULING TASKS IN THE MORNING
Wear socks
Wear shoes
Take a bath
Wear clothes
Eat breakfast
Cook breakfas
t
Get inside a car
Drive to campus
Get schoolbag
Brew a cup of coffee
Drink coffee
TOPOLOGICAL SORTING
Topological sort of a directed graph is a linear ordering of its vertices such that for every directed edge (uv), vertex u comes before vertex v in the ordering
Only possible iff the graph does not have any directed cycle
D
E
C
D
E
C
OK Not OK
PROBLEMSCHEDULING TASKS IN THE MORNING
Wear socks
Wear shoes
Take a bath
Wear clothes
Eat breakfast
Cook breakfas
t
Get inside a car
Drive to campus
Get schoolbag
Brew a cup of coffee
Drink coffee
in=1
in=2 out=3
out=8
in=4 out=7
Eat breakfast
Drive to campus
Drink coffee
Cook breakfas
t
in=9 out=10
in=5 out=6
Take a bath
in=15 out=20
Wear socks
in=11 out=14Wear
clothes
in=16 out=19Get inside
a car
in=17 out=18
Wear shoes
in=12 out=13
Get schoolbag
in=21 out=22
Descending sort by “out” : Get schoolbag(22) – Take a bath(20) – Wear clothes(19) – Get inside a car(18) – Wear socks (14) – Wear shoes (13) – Cook Breakfast(10) – Brew a cup of coffee(8) – Eat Breakfast(7) – Drive to campus(6) – Drink coffee(3)
Descending sort by “out” : Get schoolbag(22) – Take a bath(20) –
Wear clothes(19) – Get inside a car(18) – Wear socks (14) – Wear shoes (13) –
Cook Breakfast(10) – Brew a cup of coffee(8) – Eat Breakfast(7) – Drive to
campus(6) – Drink coffee(3)
PROBLEMSCHEDULING TASKS
IN THE MORNING
Wear socks
Wear shoes
Take a bath
Wear clothes
Eat breakfast
Cook breakfas
t
Get inside a car
Drive to campus
Get schoolbag
Brew a cup of coffee
Drink coffee
TOPOLOGICAL SORTINGALGORITHM// global variable ctr = 1// global stack S = empty stack
DFS(G)initialize ord_in[0..n] to 0initialize ord_out[0..n] to 0for each unvisited vertex v of G
DFS_RECURSIVE(v)return S
DFS_RECURSIVE(x)ord_in[x] = ctrctr = ctr+1process(x)for each vertex v adjacent to x
if ord_in[v] != 0 AND ord_out[v] == 0stop, graph is not DAG
else if ord_in[v] == 0 //unvisitedDFS_RECURSIVE(v)
S.push(x)ord_out[x] = ctrctr = ctr + 1
EXERCISE
Find the topological order for these vertices !
D
E
B
F
G
C
I
A
H
JK
BFS ALGORITHM
Suppose that we want to find a shortest path between two specific vertices in a graph (a path connecting the vertices with the property that no other path connecting those vertices has fewer edges)
The classical method for accomplishing this task is breadth-first search
Can be easily implemented with a queue
BFS TREE PROPERTY
Recall…
D
E
B
F G
C
I
A
H
D
E
B
F G
C
I
A
HD
E
B
F G CI
A
H
BFS Tree
For any vertex v in the BFS tree rooted at r, the tree path
from r to v corresponds to a shortest path from r to v in the corresponding graph
BFS ALGORITHM
BFS(G)Q = empty queueinitialize isVisited[0..n] to false
for each unvisited vertex v of GQ.enqueue(v)isVisited[v] = truewhile(Q is not empty)
x = Q.dequeue()process(x)for each unvisited vertex u
adjacent to xisVisited[v] = trueQ.enqueue(u)
Simple BFS Algorithm
BFS ALGORITHM
To find the shortest path from any node to the root, we need to store the BFS traversal tree Adds array parent to store the parent of each
node
Similar to DFS algorithm, we might want to know the order the vertices visited Use array ord to store the order each vertex
visited
BFS ALGORITHM
BFS(G)ctr = 1Q = empty queueinitialize ord[0..n] to 0initialize parent[0..n] to 0
for each unvisited vertex v of GQ.enqueue(v)ord[v] = ctrctr = ctr+1while(Q is not empty)
x = Q.dequeue()process(x)for each unvisited vertex u
adjacent to xparent[u] = xord[x] = ctrctr = ctr+1Q.enqueue(u)
BFS Algorithm with parent and ord arrays
BFS ALGORITHM
Same as DFS, BFS algorithm also able to solve basic connectivity problems, such as: flood fill, counting component, spanning tree.Note: topological sort is not a connectivity problem
The solutions of these problems only depends of the ability to examine every vertex of the graph, not the order we visit the vertices
DFS V.S. BFS
D
E
B
F G
C
I
A
H
D
EB
F
G
C
I
A
H
DFS Tree
D
E
B
F G CI
A
H
BFS TreeConsider our previous exampleDFS tree has several interesting
properties such as down/back edge, which is useful to solve some important problems (i.e., finding bridge and articulation point)
However, DFS tree is usually deep. Computer program usually has a limitation on how much recursive calls possible, so for large graph, recursive DFS might not feasible. In such case, we use BFS (or iterative version of DFS)
DFS V.S. BFSEXAMPLE
Tree height = #vertices = n2 Tree height = 2n-1
TIME COMPLEXITY
Graph traversal is meant to visit each vertex exactly once, thus there might be some edges remain unvisited seems like O(#vertices)
In practice we still need to visit every edges (including the chords) to check whether the vertex on its other end is already visited
So the time complexity for traversing a graph with V vertices and E edges is O(V+E) for adjacency list representation O(V2) for adjacency matrix representation