CSE 373 Section 6
Graphs
Grab a handout!
If time - leetcode
(keep computer handy)
Agenda
Announcements
MicroTeach: Graph Intro
Graphs
Graph: A set of nodes (also called vertices) connected pairwise by edges.�
Graph Terminology
Some Graph Types
a
b
d
c
a
b
d
c
e
a
b
d
c
a
b
d
c
Acyclic:
Cyclic:
Directed
Undirected
Graph Applications
Graph Applications
Everything is a graph → everything can be solved with a graph algorithm
Graph Representations
a
b
d
c
e
Questions?
MicroTeach: DFS/BFS
BFS Pseudocode (simplified)
Queue q
add Vertex start to q
mark start as discovered
while q is not empty {
Vertex from = q.remove()
for each edge {from,d} {
if d is not discovered {
add d to q
mark d as discovered
}
}
}
Why a queue?
BFS Pseudocode (simplified)
Queue q
add Vertex start to q
mark start as discovered
while q is not empty {
Vertex from = q.remove()
for each edge {from,d} {
if d is not discovered {
add d to q
mark d as discovered
}
}
}
Why a queue? FIFO; next in line is in the closest undiscovered layer to vertex
BFS Pseudocode
bfs(Graph graph, Vertex start) {
// stores the remaining vertices to visit in the BFS
Queue<Vertex> perimeter = new Queue<>();
// stores the set of discovered vertices so we don't revisit them multiple times
Set<Vertex> discovered = new Set<>();
// kicking off our starting point by adding it to the perimeter
perimeter.add(start);
discovered.add(start);
while (!perimeter.isEmpty()) {
Vertex from = perimeter.remove();
for (E edge : graph.outgoingEdgesFrom(from)) {
Vertex to = edge.to();
if (!discovered.contains(to)) {
perimeter.add(to);
discovered.add(to);
}
}
}
}
DFS Pseudocode (simplified)
Stack s
add Vertex start to s
while s is not empty {
Vertex from = s.remove()
if from is not discovered {
for each edge {from,d} {
add d to s
}
mark from as discovered
}
}
* Fixes the “bug” Sonia mentioned in Lecture 14! Can you spot the change? :)
Why a stack?
DFS Pseudocode (simplified)
Stack s
add Vertex start to s
while s is not empty {
Vertex from = s.remove()
if from is not discovered {
for each edge {from,d} {
add d to s
}
mark from as discovered
}
}
* Fixes the “bug” Sonia mentioned in Lecture 14! Can you spot the change? :)
Why a stack? LIFO: next in line is the deepest next vertex
DFS Pseudocode
dfs(Graph graph, Vertex start) {
// stores the remaining vertices to visit in the DFS
Stack<Vertex> perimeter = new Stack<>();
// stores the set of discovered vertices so we don't revisit them multiple times
Set<Vertex> discovered = new Set<>();
// kicking off our starting point by adding it to the perimeter
perimeter.add(start);
while (!perimeter.isEmpty()) {
Vertex from = perimeter.remove();
if (!discovered.contains(from)) {
for (E edge : graph.outgoingEdgesFrom(from)) {
Vertex to = edge.to();
perimeter.add(to);
}
discovered.add(from);
}
}
}
* Fixes the “bug” Sonia mentioned in Lecture 14! Can you spot the change? :)
Problem 3:
Simulating BFS
7 min
Simulating BFS
Y
S
Z
T
X
Vertex | Pred | Processed (?) |
S | -- | |
T | -- | |
X | -- | |
Y | -- | |
Z | -- | |
S | | | | |
Queue of Vertices to Explore:
Begin with the start vertex in the queue!
Simulating BFS
Y
S
Z
T
X
Vertex | Pred | Processed (?) |
S | -- | ✓ |
T | -- | |
X | -- | |
Y | -- | |
Z | `-- | |
| | | | |
Queue of Vertices to Explore:
Remove S to explore!
Simulating BFS
Y
S
Z
T
X
Vertex | Pred | Processed (?) |
S | -- | ✓ |
T | S | |
X | -- | |
Y | S | |
Z | -- | |
T | Y | | | |
Queue of Vertices to Explore:
Add neighbors of S in to queue to be explored
(order depends on the problem - sometimes arbitrary, sometimes numerical/alphabetical)
Simulating BFS
Y
S
Z
T
X
Vertex | Pred | Processed (?) |
S | -- | ✓ |
T | S | ✓ |
X | -- | |
Y | S | |
Z | -- | |
Y | | | | |
Queue of Vertices to Explore:
Remove T to explore!
Simulating BFS
Y
S
Z
T
X
Vertex | Pred | Processed (?) |
S | -- | ✓ |
T | S | ✓ |
X | T | |
Y | S | |
Z | T | |
Y | X | Z | | |
Queue of Vertices to Explore:
Add neighbors of T in to queue to be explored
Simulating BFS
Y
S
Z
T
X
Vertex | Pred | Processed (?) |
S | -- | ✓ |
T | S | ✓ |
X | T | |
Y | S | ✓ |
Z | T | |
X | Z | | | |
Queue of Vertices to Explore:
Remove Y to explore!
Simulating BFS
Y
S
Z
T
X
Vertex | Pred | Processed (?) |
S | -- | ✓ |
T | S | ✓ |
X | T | |
Y | S | ✓ |
Z | T | |
(Nothing happens!)
X | Z | | | |
Queue of Vertices to Explore:
Simulating BFS
Y
S
Z
T
X
Vertex | Pred | Processed (?) |
S | -- | ✓ |
T | S | ✓ |
X | T | ✓ |
Y | S | ✓ |
Z | T | |
Z | | | | |
Queue of Vertices to Explore:
Remove X to explore!
Simulating BFS
Y
S
Z
T
X
Vertex | Pred | Processed (?) |
S | -- | ✓ |
T | S | ✓ |
X | T | ✓ |
Y | S | ✓ |
Z | T | |
Z | | | | |
Queue of Vertices to Explore:
(Nothing happens!)
Simulating BFS
Y
S
Z
T
X
Vertex | Pred | Processed (?) |
S | -- | ✓ |
T | S | ✓ |
X | T | ✓ |
Y | S | ✓ |
Z | T | ✓ |
| | | | |
Queue of Vertices to Explore:
Pop Z to explore!
Simulating BFS
Y
S
Z
T
X
Vertex | Pred | Processed (?) |
S | -- | ✓ |
T | S | ✓ |
X | T | ✓ |
Y | S | ✓ |
Z | T | ✓ |
(Nothing happens!)
| | | | |
Queue of Vertices to Explore:
How do we interpret the final table?
Simulating BFS
Vertex | Pred | Processed (?) |
S | -- | ✓ |
T | S | ✓ |
X | T | ✓ |
Y | S | ✓ |
Z | T | ✓ |
To check if there exists a path from a given start node to given target…
To find the resulting shortest paths tree (SPT)…
Simulating BFS
Y
S
Z
T
X
Vertex | Pred | Processed (?) |
S | -- | ✓ |
T | S | ✓ |
X | T | ✓ |
Y | S | ✓ |
Z | T | ✓ |
Resulting SPT
Questions?
Problem 2:
Graph Traversal
Start at vertex “A”: only DFS
7 min
D
H
A
F
E
C
B
G
If we traverse this using breadth-first search, what are the two possible orderings of the nodes we visit?
What if we use depth-first search?
Questions?
Dijkstra’s
why this works
next week!
Vertex | Dist | Pred | Processed (?) |
S | | -- | |
T | | -- | |
X | | -- | |
Y | | -- | |
Z | | -- | |
Questions?
Summary of Applications so Far
Leetcode Problem: Find if Path Exists
(https://leetcode.com/problems/find-if-path-exists-in-graph/)
Leetcode!
Before coding the solution…
Explorations
Explorations
Explorations
Solution
public boolean validPath(int n, int[][] edges, int source, int destination) {
// source = starting vertex
// destination = terminating vertex
Queue<Integer> perimeter = new LinkedList<>();
Set<Integer> visited = new TreeSet<>();
perimeter.add(source);
visited.add(source);
while (!perimeter.isEmpty()) {
int from = perimeter.remove();
// "base case" of no recursion
if (from == destination) { return true; }
// check what edges exist around vertex
List<Integer> connectedTo = findEdges(edges, from);
for (int vertex : connectedTo) {
if (!visited.contains(vertex)) {
perimeter.add(vertex);
visited.add(vertex);
}
}
}
return false;
}
// manually implement finding the outgoing edges
private List<Integer> findEdges(int[][] edges, int from) {
List<Integer> ret = new ArrayList<Integer>();
for (int[] edge : edges) {
if (edge[0] == from) {
ret.add(edge[1]);
}
if (edge[1] == from) {
ret.add(edge[0]);
}
}
return ret;
}
MicroTeach: Dijkstra’s
Dijkstra’s Algorithm: single-pair-shortest-path
Dijkstra’s Pseudocode
Dijkstra(Graph G, Vertex source)
initialize distances to ∞
mark all vertices unprocessed
mark source as distance 0
while(there are unprocessed vertices){
let u be the closest unprocessed vertex
for each(edge (u,v) leaving u){
if(u.dist+weight(u,v) < v.dist){
v.dist = u.dist+weight(u,v)
v.predecessor = u
}
}
mark u as processed
}
Q: How to get the shortest path?
A: After running Dijkstra, start from the target node and follow the backpointers!�
GetPath(Graph G, Vertex source, Vertex target)
// We never reached the target :(
if (target.dist == INFINITY)
return null
path = []
curNode = target
path.add_back(target)
while(curNode != source)
curNode = curNode.predecessor
path.add_back(curNode)�
// If we want the path to go from source -> goal.
return path.reversed()
Problem 4A: Dijkstra
Problem 4A: Dijkstra
Y
S
Z
T
X
6
7
8
9
7
3
2
5
4
Vertex | Distance | Pred | Processed (?) |
S | 0 | -- | |
T | inf | -- | |
X | inf | -- | |
Y | inf | -- | |
Z | inf | -- | |
Problem 4A: Dijkstra
Y
S
Z
T
X
6
7
8
9
7
3
2
5
4
Vertex | Distance | Pred | Processed (?) |
S | 0 | -- | ✓ |
T | inf | -- | |
X | inf | -- | |
Y | inf | -- | |
Z | inf | -- | |
Problem 4A: Dijkstra
Y
S
Z
T
X
6
7
8
9
7
3
2
5
4
Vertex | Distance | Pred | Processed (?) |
S | 0 | -- | ✓ |
T | inf 6 | S | |
X | inf | -- | |
Y | inf 7 | S | |
Z | inf | -- | |
Problem 4A: Dijkstra
Y
S
Z
T
X
6
7
8
9
7
3
2
5
4
Vertex | Distance | Pred | Processed (?) |
S | 0 | -- | ✓ |
T | inf 6 | S | ✓ |
X | inf | -- | |
Y | inf 7 | S | |
Z | inf | -- | |
Problem 4A: Dijkstra
Y
S
Z
T
X
6
7
8
9
7
3
2
5
4
Vertex | Distance | Pred | Processed (?) |
S | 0 | -- | ✓ |
T | inf 6 | S | ✓ |
X | inf 11 | T | |
Y | inf 7 | S | |
Z | inf 10 | T | |
Problem 4A: Dijkstra
Y
S
Z
T
X
6
7
8
9
7
3
2
5
4
Vertex | Distance | Pred | Processed (?) |
S | 0 | -- | ✓ |
T | inf 6 | S | ✓ |
X | inf 11 | T | |
Y | inf 7 | S | ✓ |
Z | inf 10 | T | |
Problem 4A: Dijkstra
Y
S
Z
T
X
6
7
8
9
7
3
2
5
4
Vertex | Distance | Pred | Processed (?) |
S | 0 | -- | ✓ |
T | inf 6 | S | ✓ |
X | inf 11 10 | T Y | |
Y | inf 7 | S | ✓ |
Z | inf 10 | T | |
Problem 4A: Dijkstra
Y
S
Z
T
X
6
7
8
9
7
3
2
5
4
Vertex | Distance | Pred | Processed (?) |
S | 0 | -- | ✓ |
T | inf 6 | S | ✓ |
X | inf 11 10 | T Y | ✓ |
Y | inf 7 | S | ✓ |
Z | inf 10 | T | |
Problem 4A: Dijkstra
Y
S
Z
T
X
6
7
8
9
7
3
2
5
4
Vertex | Distance | Pred | Processed (?) |
S | 0 | -- | ✓ |
T | inf 6 | S | ✓ |
X | inf 11 10 | T Y | ✓ |
Y | inf 7 | S | ✓ |
Z | inf 10 | T | |
(Nothing happens!)
Problem 4A: Dijkstra
Y
S
Z
T
X
6
7
8
9
7
3
2
5
4
Vertex | Distance | Pred | Processed (?) |
S | 0 | -- | ✓ |
T | inf 6 | S | ✓ |
X | inf 11 10 | T Y | ✓ |
Y | inf 7 | S | ✓ |
Z | inf 10 | T | ✓ |
Problem 4A: Dijkstra
Y
S
Z
T
X
6
7
8
9
7
3
2
5
4
Vertex | Distance | Pred | Processed (?) |
S | 0 | -- | ✓ |
T | inf 6 | S | ✓ |
X | inf 11 10 | T Y | ✓ |
Y | inf 7 | S | ✓ |
Z | inf 10 | T | ✓ |
(Nothing happens!)
Problem 4A: Dijkstra
Y
S
Z
T
X
6
7
8
9
7
3
2
5
4
Vertex | Distance | Pred | Processed (?) |
S | 0 | -- | ✓ |
T | inf 6 | S | ✓ |
X | inf 11 10 | T Y | ✓ |
Y | inf 7 | S | ✓ |
Z | inf 10 | T | ✓ |
Problem 4A: Dijkstra
Y
S
Z
T
X
6
7
8
9
7
3
2
5
4
Vertex | Distance | Pred | Processed (?) |
S | 0 | -- | ✓ |
T | inf 6 | S | ✓ |
X | inf 11 10 | T Y | ✓ |
Y | inf 7 | S | ✓ |
Z | inf 10 | T | ✓ |
Resulting SPT
Why It Works - Understanding Dijkstra Invariants
Invariants
predecessor[v]: best known predecessor of v.
distTo[v]: best known distance of s to v.
PQ maintains vertices based on distTo.
Important properties
Always visits vertices in order of total distance from source.
Problem 6: DJ Kistra
Problem 6
Problem 6A
(a) Describe a graph you could construct to help you solve the problem. At the very least you’ll want to mention what the vertices and edges are, and whether the edges are weighted or unweighted and directed or undirected.
Problem 6A
Q: How do we get from Shake It Off to Wildest Dreams while obeying the rule:
Two consecutive songs’ tempos must differ by no more than 10 beats per minute (BPM)
Shake It Off
Wildest Dreams
Problem 6A
Shake It Off
Let vertices be songs!
Love
Song
22
Lover
Wildest Dreams
But how do we know if two songs’ tempos differ by more than 10 BPM?
Problem 6A
Shake It Off
150 BPM
Include BPM in vertices!
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Storing multiple pieces of information in Vertex or Edge Objects is often useful.
Problem 6A
Shake It Off
150 BPM
Q: What are our edges?
We know we want to slow down the tempo and create a path between Shake It Off and Wildest Dreams.
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Problem 6A
Shake It Off
150 BPM
Let edges represent valid song transitions!
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Allow the DJ to play the next song only if its tempo is slower and within 10 BPM of the current song.
Problem 6A
Shake It Off
150 BPM
Let edges represent valid song transitions!
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Allow the DJ to play the next song only if its tempo is slower and within 10 BPM of the current song.
valid?
Problem 6A
Shake It Off
150 BPM
Let edges represent valid song transitions!
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Directed or Undirected?
Directed: We don’t want to play a song we already played since it has a faster tempo and is farther away from Wildest Dreams.
Problem 6A
|
|
💯
👀
Can we accomplish the task with the graph model we’ve built? Let’s check.
There’s more information we haven’t used. Does the length of the songs help us?
We don’t have a way to prioritize between different possible song transitions!
Problem 6A
Shake It Off
150 BPM
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Q: Once we have edges, how do we know which path between Shake It Off and Wildest Dreams will take the least amount of time?
Looks like we need to encode more information in our graph.
Problem 6A
Shake It Off
150 BPM
Let edge weights be the length of the next song!
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Let’s think ahead: why does this help us decide which path will take the shortest amount of time?
We’ll use this information later when we run an algorithm on our graph to find the list of songs that take the least time.
237 sec.
Problem 6A
Shake It Off
150 BPM
Let edge weights be the length of the next song!
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Which algorithm can make use of edge weights to give us a shortest path?
237 sec.
Dijkstra’s!
Problem 6A
Shake It Off
150 BPM
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Now our graph model has everything it needs to find the shortest path between Shake It Off and Wildest Dreams!
237 sec.
Vertices: song and BPM
Edges: valid song transitions
Weights: next song length
Problem 6B
(b) Describe an algorithm to construct your graph from the previous part. You may assume your songs are stored in whatever data structure makes this part easiest. Assume you have access to a method makeEdge(v1, v2, w) which creates an edge from v1 to v2 of weight w.
Problem 6B
Shake It Off
150 BPM
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
valid?
Let’s continue making edges and see if we can turn the process into an algorithm.
237 sec.
Vertices: song and BPM
Edges: valid song transitions
Weights: next song length
Problem 6B
Shake It Off
150 BPM
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Allow the DJ to play the next song only if its tempo is slower and within 10 BPM of the current song.
Vertices: song and BPM
Edges: valid song transitions
Weights: next song length
237 sec.
Problem 6B
Shake It Off
150 BPM
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Allow the DJ to play the next song only if its tempo is slower and within 10 BPM of the current song.
valid?
Vertices: song and BPM
Edges: valid song transitions
Weights: next song length
237 sec.
Problem 6B
Shake It Off
150 BPM
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Allow the DJ to play the next song only if its tempo is slower and within 10 BPM of the current song.
Vertices: song and BPM
Edges: valid song transitions
Weights: next song length
237 sec.
Problem 6B
Shake It Off
150 BPM
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Allow the DJ to play the next song only if its tempo is slower and within 10 BPM of the current song.
valid?
Vertices: song and BPM
Edges: valid song transitions
Weights: next song length
237 sec.
Problem 6B
Shake It Off
150 BPM
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Allow the DJ to play the next song only if its tempo is slower and within 10 BPM of the current song.
Vertices: song and BPM
Edges: valid song transitions
Weights: next song length
237 sec.
Problem 6B
Shake It Off
150 BPM
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Algorithm: Check every pair of vertices and add an edge if it’s valid.
valid?
valid?
valid?
valid?
Vertices: song and BPM
Edges: valid song transitions
Weights: next song length
237 sec.
Problem 6B
Shake It Off
150 BPM
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Algorithm: Check every pair of vertices and add an edge if it’s valid.
Vertices: song and BPM
Edges: valid song transitions
Weights: next song length
237 sec.
Problem 6B
Shake It Off
150 BPM
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Algorithm: Check every pair of vertices and add an edge if it’s valid.
Vertices: song and BPM
Edges: valid song transitions
Weights: next song length
237 sec.
205 sec.
Problem 6B
Shake It Off
150 BPM
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Algorithm: Check every pair of vertices and add an edge if it’s valid.
Vertices: song and BPM
Edges: valid song transitions
Weights: next song length
237 sec.
205 sec.
Are these valid?
Problem 6B
Shake It Off
150 BPM
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Algorithm: Check every pair of vertices and add an edge if it’s valid.
Vertices: song and BPM
Edges: valid song transitions
Weights: next song length
237 sec.
205 sec.
Problem 6B
Shake It Off
150 BPM
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Algorithm: Check every pair of vertices and add an edge if it’s valid.
Vertices: song and BPM
Edges: valid song transitions
Weights: next song length
237 sec.
205 sec.
187 sec.
Are these valid?
Problem 6B
Shake It Off
150 BPM
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Algorithm: Check every pair of vertices and add an edge if it’s valid.
Vertices: song and BPM
Edges: valid song transitions
Weights: next song length
237 sec.
205 sec.
187 sec.
Problem 6B
Shake It Off
150 BPM
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Algorithm: Check every pair of vertices and add an edge if it’s valid.
Vertices: song and BPM
Edges: valid song transitions
Weights: next song length
237 sec.
205 sec.
187 sec.
222 sec.
Problem 6B
Shake It Off
150 BPM
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Algorithm: Check every pair of vertices and add an edge if it’s valid.
Vertices: song and BPM
Edges: valid song transitions
Weights: next song length
237 sec.
205 sec.
187 sec.
222 sec.
Are these valid?
Problem 6B
Shake It Off
150 BPM
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Algorithm: Check every pair of vertices and add an edge if it’s valid.
Vertices: song and BPM
Edges: valid song transitions
Weights: next song length
237 sec.
205 sec.
187 sec.
222 sec.
Problem 6B
Shake It Off
150 BPM
Love
Song
140 BPM
22
150 BPM
Lover
130 BPM
Wildest Dreams
120 BPM
Ta-da! This is our graph :)
Vertices: song and BPM
Edges: valid song transitions
Weights: next song length
237 sec.
205 sec.
187 sec.
222 sec.
Problem 6B
Problem 6C
(c) Describe an algorithm you could run on the graph you just constructed to find the list of songs you can play to get to “Wildest Dreams” the fastest without disappointing the crowd.
Problem 6D
(d) What is the running time of your plan to find the list of songs? You should include the time it would take to construct your graph and to find the list of songs. Give a simplified big-O running time in terms of whatever variables you need.
Problem 6D
How long did it take to construct our graph?
We then run Dijkstra’s starting from Shake It Off. What’s the runtime of Dijkstra’s?
O(S2)
O(E*log(S) + S*log(S))
O(S2 + E*log(S) + S*log(S))
What’s the total runtime to find the list of songs the DJ should play?
Is this simplified?
S2 dominates S*log(S) so we can ignore the smaller term!
Total runtime: O(S2 + E*log(S))