1 of 62

Graphs

CSE 332 – Section 6

Slides by James Richie Sulaeman

2 of 62

Graphs

3 of 62

A graph is a set of vertices connected by edges

  • A vertex is also known as a node
  • An edge is represented as a pair of vertices

Graphs

A

D

B

E

F

C

vertices

edges

example of a undirected,

unweighted, cyclic graph

4 of 62

  • Degree of vertex V
    • Number of edges connected to vertex V
    • In-degree: number of edges going into vertex V
    • Out-degree: number of edges going out of vertex V
  • Weight of edge e
    • Numerical value/cost associated with traversing edge e
  • Path
    • A sequence of adjacent vertices connected by edges
  • Cycle
    • A path that begins and ends at the same vertex

Graph Terminology

5 of 62

Graph Terminology (continue)

B

C

A

B

C

A

B

C

A

directed, weighted, cyclic graph

directed, unweighted, acyclic graph

undirected, unweighted, acyclic graph

B

C

A

undirected, weighted, cyclic graph

  • Directed vs. undirected graphs
    • Edges can have direction (i.e. bidirectional vs. unidirectional)
  • Weighted vs. unweighted graphs
    • Edges can have weights/costs (e.g. how many minutes to go from vertex A to B)
  • Cyclic vs. acyclic graphs
    • Graph contains a cycle

5

3

7

1

3

5

7

6 of 62

Graph Traversals

7 of 62

  • Depth First Search (DFS)
    • Visit all nodes reachable by a neighbor before another
    • Can be implemented recursively/by using a stack
    • O(|V| + |E|) runtime

Graph Traversals

Depth First Search (DFS)

Breadth First Search (BFS)

  • Breadth First Search (BFS)
    • Explores the graph level by level
    • Implemented using a queue
    • Finds the shortest path in an unweighted graph
    • O(|V| + |E|) runtime

How do we iterate through a graph?

(not recommend)

8 of 62

Depth First Search

DFS(Graph g, Vertex curr):

mark curr as visited

for (v : neighbors(current)):

if (!v marked “visited”)

DFS(g, v)

mark curr as “done”;

  • Explores the graph: visiting all nodes reachable by one neighbor before selecting another. (as deep as possible)
  • Implemented recursively/by using a stack
  • O(|V| + |E|) runtime

Depth First Search (DFS)

(not recommend)

9 of 62

Breadth First Search

BFS(Vertex start):

initialize queue q to hold start

mark start as visited

while q is not empty:

vertex v = q.dequeue()

for each neighbour u of v:

if u is not visited:

mark u as visited

predecessor[u] = v

add u to q

  • Explores the graph level by level
  • Implemented using a queue
  • Finds the shortest path in an unweighted graph
  • O(|V| + |E|) runtime

Breadth First Search (BFS)

10 of 62

Problem 0

BFS(Vertex start):

initialize queue q to hold start

mark start as visited

while q is not empty:

vertex v = q.dequeue()

for each neighbour u of v:

if u is not visited:

mark u as visited

predecessor[u] = v

add u to q

11 of 62

Problem 0 (1)

S

T

Z

X

Y

Queue:

front

back

  • Initialize queue to hold starting vertex S
  • Mark vertex S as visited

S

S

Vertex

Predecessor

Visited?

S

No

T

No

X

No

Y

No

Z

No

Yes

12 of 62

S

T

Z

X

Y

Queue:

front

back

  • Dequeue vertex S
  • Add neighbors T, Y to the queue

T

S

Y

T

S

Vertex

Predecessor

Visited?

S

Yes

T

No

X

No

Y

No

Z

No

Y

Yes

S

S

Yes

Problem 0 (2)

13 of 62

Y

S

T

Z

X

Y

Queue:

front

back

  • Dequeue vertex T
  • Add neighbors X, Z to the queue

(ignore Y since already visited)

S

Y

T

Z

X

Vertex

Predecessor

Visited?

S

Yes

T

S

Yes

X

No

Y

S

Yes

Z

No

Yes

X

T

Yes

T

T

Z

Problem 0 (3)

14 of 62

X

Z

S

T

Z

X

Y

Queue:

front

back

  • Dequeue vertex Y
  • Add neighbors to the queue

(nothing happens since all already visited)

S

Y

T

Z

X

Y

Vertex

Predecessor

Visited?

S

Yes

T

S

Yes

X

T

Yes

Y

S

Yes

Z

T

Yes

Problem 0 (4)

15 of 62

Z

S

T

Z

X

Y

Queue:

front

back

  • Dequeue vertex X
  • Add neighbors to the queue

(nothing happens since all already visited)

S

Y

T

Z

X

Vertex

Predecessor

Visited?

S

Yes

T

S

Yes

X

T

Yes

Y

S

Yes

Z

T

Yes

X

Problem 0 (5)

16 of 62

S

T

Z

X

Y

Queue:

front

back

  • Dequeue vertex Z
  • Add neighbors to the queue

(nothing happens since all already visited)

S

Y

T

Z

X

Vertex

Predecessor

Visited?

S

Yes

T

S

Yes

X

T

Yes

Y

S

Yes

Z

T

Yes

Z

Problem 0 (6)

17 of 62

S

T

Z

X

Y

Queue:

front

back

  • Queue is empty; we are done

S

Y

T

Z

X

Vertex

Predecessor

Visited?

S

Yes

T

S

Yes

X

T

Yes

Y

S

Yes

Z

T

Yes

Problem 0 (7)

18 of 62

BFS Table Interpretation

19 of 62

Vertex

Predecessor

Visited?

S

Yes

T

S

Yes

X

T

Yes

Y

S

Yes

Z

T

Yes

BFS Table Interpretation

  • A path exists if and only if the target node has a predecessor in the table

How to find a path from the start node to a target node?

  • Locate the target node in the table
  • Backtrack through its predecessors until you reach the start node
  • The sequence of predecessors form a path from the start to the target
  • Will be the shortest path by edge count (but not necessarily sum of edge costs)

How to check if a path exists from the start node to a target node?

20 of 62

Problem 1

DFS(Graph g, Vertex curr):

mark curr as visited

for (v : neighbors(current)):

if (!v marked “visited”)

DFS(g, v)

mark curr as “done”;

21 of 62

Problem 1 (1)

S

T

Z

X

Y

StackFrame (curr):

Vertex

Visited?

Done?

S

No

No

T

No

No

X

No

No

Y

No

No

Z

No

No

  • Build stack frame of dfs(g, S)
  • Mark vertex S as visited

Yes

S

S

22 of 62

S

T

Z

X

Y

StackFrame (curr):

Vertex

Visited?

Done?

S

Yes

No

T

No

No

X

No

No

Y

No

No

Z

No

No

  • S Call dfs on unvisited neighbor T
  • Mark vertex T as visited

S

T

S

Yes

T

Problem 1 (2)

23 of 62

S

T

Z

X

Y

StackFrame (curr):

Vertex

Visited?

Done?

S

Yes

No

T

Yes

No

X

No

No

Y

No

No

Z

No

No

  • T Call dfs on unvisited neighbor X
  • Mark vertex X as visited

S

T

Yes

X

T

X

Problem 1 (3)

24 of 62

S

T

Z

X

Y

StackFrame (curr):

Vertex

Visited?

Done?

S

Yes

No

T

Yes

No

X

Yes

No

Y

No

No

Z

No

No

  • No recursive call in X: all neighbors are visited
  • Mark vertex X as done, exit X stack frame

S

T

X

Yes

X

Problem 1 (4)

25 of 62

S

T

Z

X

Y

StackFrame (curr):

Vertex

Visited?

Done?

S

Yes

No

T

Yes

No

X

Yes

Yes

Y

No

No

Z

No

No

  • T Call dfs on unvisited neighbor Y
  • Mark vertex Y as visited

S

T

Yes

X

Y

T

Y

Problem 1 (5)

26 of 62

S

T

Z

X

Y

StackFrame (curr):

Vertex

Visited?

Done?

S

Yes

No

T

Yes

No

X

Yes

Yes

Y

Yes

No

Z

No

No

  • Y Call dfs on unvisited neighbor Z
  • Mark vertex Z as visited

S

T

Yes

X

Y

Y

Z

Z

Problem 1 (6)

27 of 62

S

T

Z

X

Y

StackFrame (curr):

Vertex

Visited?

Done?

S

Yes

No

T

Yes

No

X

Yes

Yes

Y

Yes

No

Z

Yes

No

  • No recursive call in Z: all neighbors are visited
  • Mark vertex Z as done, exit Z stack frame

S

T

Yes

X

Y

Z

Z

Problem 1 (7)

28 of 62

S

T

Z

X

Y

StackFrame (curr):

Vertex

Visited?

Done?

S

Yes

No

T

Yes

No

X

Yes

Yes

Y

Yes

No

Z

Yes

Yes

  • Finish all recursive in Y: all neighbors are visited
  • Mark vertex Y as done, exit Y stack frame

S

T

Yes

X

Y

Z

Y

Problem 1 (8)

29 of 62

S

T

Z

X

Y

StackFrame (curr):

Vertex

Visited?

Done?

S

Yes

No

T

Yes

No

X

Yes

Yes

Y

Yes

Yes

Z

Yes

Yes

  • Finish all recursive in T: all neighbors are visited
  • Mark vertex T as done, exit T stack frame

S

T

Yes

X

Y

Z

T

Problem 1 (9)

30 of 62

S

T

Z

X

Y

StackFrame (curr):

Vertex

Visited?

Done?

S

Yes

No

T

Yes

Yes

X

Yes

Yes

Y

Yes

Yes

Z

Yes

Yes

  • Finish all recursive in S: all neighbors are visited
  • Mark vertex S as done, exit S stack frame

S

T

Yes

X

Y

Z

S

Problem 1 (10)

31 of 62

BFS/DFS Useful Properties

32 of 62

BFS - Shortest Path

  • BFS always returns the shortest path from source to any other vertex by edge count!
  • Intuition:
    • Each step push neighbors that are one edge away, onto a queue.
    • Because we use a queue, we must process the vertices 1 edge away, before vertices farther away
    • Each vertex’s predecessor in the table is the one which initially pushes it onto the queue (earliest/shortest path)

33 of 62

DFS - Cycle Detection

  • DFS can be used to detect cycles in graphs
  • Intuition:
    • Each step push neighbors that are one edge away from the current node onto a stack.
    • Because we use a stack, we process the vertices further away, before the vertices close to the source
    • If we ever see a vertex to a node currently on the stack, we know a back edge and thus a cycle exists

34 of 62

Start from A

Detect Cycle Examples

  • Use DFS to detect cycle by finding a back edge
  • a back edge is an edge that connects a node to one of its ancestors in the current recursion stack.

A

E

B

D

C

35 of 62

Vertex: B

Vertex: B

Mark B as visited

Vertex: A

Vertex: A

Mark A as visited

A

E

B

D

C

Start from A

No Cycle Example

__ - Visited

__ - Done

A

B

Vertex: B

Mark B as done

B

C

Vertex: C

Mark C as visited

D

Vertex: D

Mark D as visited

E

Vertex: E

Mark E as visited

E

Vertex: E

Mark E as done

D

Vertex: D

Mark D as done

C

Vertex: C

Mark C as done

A

Vertex: A

Mark A as done

36 of 62

A

D

E

C

B

Start from A

Vertex: A

Vertex: B

Vertex: C

Mark C as visited

Vertex: D

Mark D as visited

Vertex: B

Mark B as visited

Vertex: C

Mark C as visited

Vertex: D

Mark as done

Edge points to a visited node, back edge detected!

Vertex: A

Mark A as visited

Vertex: E

Mark E as visited

Vertex: B

Go to next unvisited

With Cycle Example

A

B

C

D

D

E

Vertex: C

Mark C as done

C

B

Vertex: E

Mark E as done

E

A

Vertex: A

Mark A as done

Vertex: B

Mark B as done

37 of 62

Problem 2: Detecting Cycles

38 of 62

Problem 2 (0)

S

X

Y

Z

U

Vertex

Visited?

Done?

Cycles Detected at Vertex

S

No

No

None

U

No

No

None

X

No

No

None

Y

No

No

None

Z

No

No

None

  • Build stack frame of dfs(g, S)
  • Mark vertex S as visited

Yes

S

StackFrame (curr):

S

39 of 62

U

Problem 2 (1)

S

X

Y

Z

U

StackFrame (curr):

  • S Call dfs on unvisited neighbor U
  • Mark vertex U as visited

S

S

U

Vertex

Visited?

Done?

Cycles Detected at Vertex

S

Yes

No

None

U

No

No

None

X

No

No

None

Y

No

No

None

Z

No

No

None

Yes

40 of 62

U

Problem 2 (2)

S

X

Y

Z

StackFrame (curr):

  • No recursive call in U: all neighbors are visited
  • Mark vertex U as done

S

S

U

Vertex

Visited?

Done?

Cycles Detected at Vertex

S

Yes

No

None

U

Yes

No

None

X

No

No

None

Y

No

No

None

Z

No

No

None

Yes

U

41 of 62

U

Problem 2 (3)

S

X

Y

Z

X

StackFrame (curr):

  • S Call dfs on unvisited neighbor X
  • Mark vertex X as visited

S

S

U

Vertex

Visited?

Done?

Cycles Detected at Vertex

S

Yes

No

None

U

Yes

Yes

None

X

No

No

None

Y

No

No

None

Z

No

No

None

Yes

U

X

42 of 62

U

Problem 2 (4)

S

X

Y

Z

Y

StackFrame (curr):

  • X Call dfs on unvisited neighbor Y
  • Mark vertex Y as visited

S

S

U

Vertex

Visited?

Done?

Cycles Detected at Vertex

S

Yes

No

None

U

Yes

Yes

None

X

Yes

No

None

Y

No

No

None

Z

No

No

None

Yes

U

X

Y

  • Check neighbors of Y: back edge to X detected

(X,Y)

43 of 62

U

Problem 2 (5)

S

X

Y

Z

StackFrame (curr):

  • Y Call dfs on unvisited neighbor Z
  • Mark vertex Z as visited

S

S

U

Vertex

Visited?

Done?

Cycles Detected at Vertex

S

Yes

No

None

U

Yes

Yes

None

X

Yes

No

None

Y

Yes

No

(X,Y)

Z

No

No

None

Yes

U

X

Y

  • Check neighbors of Z: back edge to S and X detected

Z

(S,X,Y,Z), (X,Y,Z)

Z

44 of 62

U

Problem 2 (6)

S

X

Y

Z

StackFrame (curr):

  • No recursive call in Z: all neighbors are visited
  • Mark vertex Z as done

S

S

U

Vertex

Visited?

Done?

Cycles Detected at Vertex

S

Yes

No

None

U

Yes

Yes

None

X

Yes

No

None

Y

Yes

No

(X,Y)

Z

Yes

No

(S,X,Y,Z), (X,Y,Z)

Yes

X

Y

Z

Z

45 of 62

U

Problem 2 (7)

S

X

Y

Z

StackFrame (curr):

  • Finish all recursive in Y: all neighbors are visited
  • Mark vertex Y as done

S

S

U

Vertex

Visited?

Done?

Cycles Detected at Vertex

S

Yes

No

None

U

Yes

Yes

None

X

Yes

No

None

Y

Yes

No

(X,Y)

Z

Yes

Yes

(S,X,Y,Z), (X,Y,Z)

X

Y

Z

Y

Yes

46 of 62

U

Problem 2 (8)

S

X

Y

Z

StackFrame (curr):

  • Finish all recursive in X: all neighbors are visited
  • Mark vertex X as done

S

S

U

Vertex

Visited?

Done?

Cycles Detected at Vertex

S

Yes

No

None

U

Yes

Yes

None

X

Yes

No

None

Y

Yes

Yes

(X,Y)

Z

Yes

Yes

(S,X,Y,Z), (X,Y,Z)

X

Y

Z

X

Yes

47 of 62

U

S

X

Y

Z

StackFrame (curr):

  • Finish all recursive in S: all neighbors are visited
  • Mark vertex S as done

S

S

U

Vertex

Visited?

Done?

Cycles Detected at Vertex

S

Yes

No

None

U

Yes

Yes

None

X

Yes

Yes

None

Y

Yes

Yes

(X,Y)

Z

Yes

Yes

(S,X,Y,Z), (X,Y,Z)

X

Y

Z

S

Yes

Problem 2 (9)

48 of 62

Dijkstra’s Algorithm

(Shortest Path)

49 of 62

Dijkstra(Vertex source):

for each vertex v:

set v.cost = infinity

mark v as unvisited

set source.cost = 0

while exist unvisited vertices:

select unvisited vertex v with lowest cost

mark v as visited

for each edge (v, u) with weight w:

if u is not visited:

potentialBest = v.cost + w // cost of best path to u through v

currBest = u.cost // cost of current best path to u

if (potentialBest < currBest):

u.cost = potentialBest

u.pred = v

Dijkstra’s Algorithm

Dijkstra’s algorithm finds the minimum-cost path from a source vertex to every other vertex in a non-negatively weighted graph

  • O(|V| log |V| + |E| log |V|) runtime

50 of 62

Problem 3

Dijkstra(Vertex source):

for each vertex v:

set v.cost = infinity

mark v as unvisited

set source.cost = 0

while exist unvisited vertices:

select unvisited vertex v with lowest cost

mark v as visited

for each edge (v, u) with weight w:

if u is not visited:

potentialBest = v.cost + w

currBest = u.cost

if (potentialBest < currBest):

u.cost = potentialBest

u.pred = v

51 of 62

Problem 3 (1)

Vertex

Visited?

Cost

Predecessor

A

B

C

D

E

F

F

A

D

C

B

E

1

3

5

2

8

16

13

13

50

6

3

7

  • Initialize each vertex as unvisited with cost ∞
  • Set cost of source vertex A to 0

0

No

No

No

No

No

No

52 of 62

F

A

D

C

B

E

1

3

5

2

8

16

13

13

50

6

3

7

A

1

8

16

13

50

Vertex

Visited?

Cost

Predecessor

A

No

0

B

No

C

No

D

No

E

No

F

No

  • Select unvisited vertex with lowest cost (A)

Yes

  • Mark A as visited
  • Process each outgoing edge

8

16

50

13

1

A

A

A

A

A

Problem 3 (2)

53 of 62

F

A

D

C

B

E

1

3

5

2

8

16

13

13

50

6

3

7

3

13

Vertex

Visited?

Cost

Predecessor

A

Yes

0

B

No

8

A

C

No

16

A

D

No

50

A

E

No

13

A

F

No

1

A

Yes

A

F

∞ 13 4

  • Select unvisited vertex with lowest cost (F)
  • Mark F as visited
  • Process each outgoing edge

A F

Problem 3 (3)

54 of 62

F

A

D

C

B

E

1

3

5

2

8

16

13

13

50

6

3

7

5

Vertex

Visited?

Cost

Predecessor

A

Yes

0

B

No

8

A

C

No

16

A

D

No

50

A

E

No

∞ 13 4

A F

F

Yes

1

A

E

∞ 50 9

Yes

A

  • Select unvisited vertex with lowest cost (E)
  • Mark E as visited
  • Process each outgoing edge

F

A E

Problem 3 (4)

55 of 62

F

A

D

C

B

E

1

3

5

2

8

16

13

13

50

6

3

7

Vertex

Visited?

Cost

Predecessor

A

Yes

0

B

No

8

A

C

No

16

A

D

No

∞ 50 9

A E

E

Yes

∞ 13 4

A F

F

Yes

1

A

B

Yes

A

  • Select unvisited vertex with lowest cost (B)
  • Mark B as visited
  • Process each outgoing edge

F

E

  • No outgoing edges; continue

Problem 3 (5)

56 of 62

F

A

D

C

B

E

1

3

5

2

8

16

13

13

50

6

3

7

2

Vertex

Visited?

Cost

Predecessor

A

Yes

0

B

Yes

8

A

C

No

16

A

D

No

∞ 50 9

A E

E

Yes

∞ 13 4

A F

F

Yes

1

A

D

Yes

A D

A

  • Select unvisited vertex with lowest cost (D)
  • Mark D as visited
  • Process each outgoing edge

(ignore D→B since B is already visited)

F

E

B

∞ 16 11

6

Problem 3 (6)

57 of 62

F

A

D

C

B

E

1

3

5

2

8

16

13

13

50

6

3

7

7

Vertex

Visited?

Cost

Predecessor

A

Yes

0

B

Yes

8

A

C

No

∞ 16 11

A D

D

Yes

∞ 50 9

A E

E

Yes

∞ 13 4

A F

F

Yes

1

A

C

Yes

A

  • Select unvisited vertex with lowest cost (C)
  • Mark C as visited
  • Process each outgoing edge

(ignore C→B & C→E since B & E are already visited)

F

E

B

D

  • No outgoing edges to unvisited nodes; continue

3

Problem 3 (7)

58 of 62

F

A

D

C

B

E

1

3

5

2

8

16

13

13

50

6

3

7

Vertex

Visited?

Cost

Predecessor

A

Yes

0

B

Yes

8

A

C

No

∞ 16 11

A D

D

Yes

∞ 50 9

A E

E

Yes

∞ 13 4

A F

F

Yes

1

A

Yes

A

F

E

B

D

C

  • No more unvisited nodes; we are done

Problem 3 (8)

59 of 62

Problem 4

Dijkstra(Vertex source):

for each vertex v:

set v.cost = infinity

mark v as unvisited

set source.cost = 0

while exist unvisited vertices:

select unvisited vertex v with lowest cost

mark v as visited

for each edge (v, u) with weight w:

if u is not visited:

potentialBest = v.cost + w

currBest = u.cost

if (potentialBest < currBest):

u.cost = potentialBest

u.pred = v

60 of 62

Problem 4 (1)

Vertex

Visited?

Cost

Predecessor

A

B

C

D

E

F

B

A

D

E

F

C

5

3

-5

10

4

60

70

80

90

6

7

  • Initialize each vertex as unvisited with cost ∞
  • Set cost of source vertex A to 0

0

No

No

No

No

No

No

61 of 62

B

A

D

E

F

C

5

3

-5

10

4

60

70

80

90

6

7

  • Initialize each vertex as unvisited with cost ∞
  • Set cost of source vertex A to 0

Vertex

Visited?

Cost of Path

Pred

a

True

0

b

True

05

a

c

True

80 08

a b

d

True

90 03

a c

e

True

60 13

a d

f

True

04

a

Order added to known set: a, f, b, c, d, e

Problem 4 (2)

62 of 62

Thank You!