diff --git a/graph-search/notes.md b/graph-search/notes.md
index 2895d5069e1387252e3655919f124a95ae3de707..03f649113f94bfbd9659c4915b6a2a6fb908dd92 100644
--- a/graph-search/notes.md
+++ b/graph-search/notes.md
@@ -4,11 +4,13 @@ Please clone the starter code linked from Canvas (with `git clone --recursive` s
 
 In the weighted directed graph to the right, what is the shortest path from `a` to `d`?
 
+*   `a` → `c` → `e` → `f` → `d` (length 14)
+
 # Problem 2:
 
 For a certain puzzle played on a string of digits, each move may slide any digit `x` left `x` places or right `x` places, as long as there is room.  For example, the `4` in `123456789` can move right four spots:
 
->  123456789  
+>  123456789
 >      >>>>
 
 which gives
@@ -17,11 +19,14 @@ which gives
 
 but it cannot move left, because trying would move it past the end of the string:
 
->  123456789  
+>  123456789
 > <<<<
 
 How many moves does it take to reverse the string `123`?
 
+*   Four moves: `123` → `213` → `231` → `312` → `321`
+*   Four moves: `123` → `213` → `132` → `312` → `321`
+
 ---------------------------------------------------------------------
 
 # Worklist Algorithms for Graph Search
@@ -31,45 +36,70 @@ How many moves does it take to reverse the string `123`?
 
 ## Depth-First Search (DFS)
 
-*   Worklist: …
+*   Worklist: Stack
 *   Guaranteed to find a path if one exists
 *   Not guaranteed to find a good path
 *   Can be made very memory efficient (topic for a later class)
 
     Worklist    Backpointers
     --------    ------------
-    (⊥, a)
+    (⊥, a) ✓    a → (⊥, a)
+    (a, c) ✓    c → (a, c)
+    (c, e)      b → (c, b)
+    (c, b) ✓    e → (b, e)
+    (b, e) ✓    f → (e, f)
+    (b, a) ✓    d → (f, d)
+    (e, d)
+    (e, f) ✓
+    (f, c)
+    (f, d) ✓
 
     Reversed Path
     ----
-    …
+    d ← f ← e ← b ← c ← a
 
 ## Breadth-First Search (BFS)
 
-*   Worklist: …
+*   Worklist: Queue
 *   Guaranteed to find a path with the fewest edges
 
     Worklist    Backpointers
     --------    ------------
-    (⊥, a)
+    (⊥, a) ✓    a → (⊥, a)
+    (a, c) ✓    c → (a, c)
+    (c, e) ✓    e → (c, e)
+    (c, b) ✓    b → (c, b)
+    (e, d) ✓    d → (e, d)
+    (e, f)
+    (b, e)
+    (b, a)
 
     Reversed Path
     ----
-    …
+    d ← e ← c ← a
 
 ## Dijkstra's Algorithm
 
-*   Worklist: …
-*   Priority: …
+*   Worklist: Priority Queue
+*   Priority: Distance traveled from the source
 *   Guaranteed to find a path with least weight
 
       Worklist       Backpointers
     ------------    --------------
-    (⊥, a, 0)
+    (⊥, a, 0) ✓     a → (⊥, a, 0)
+    (a, c, 7) ✓     c → (a, c, 7)
+    (c, e, 12) ✓    b → (c, b, 8)
+    (c, b, 8) ✓     e → (c, e, 12)
+    (b, e, 17)      f → (e, f, 14)
+    (b, a, 12) ✓    d → (f, d, 14)
+    (e, d, 15)
+    (e, f, 14) ✓
+    (f, c, 22)
+    (f, d, 14) ✓
 
     Reversed Path
     ----
-    …
+    d ← f ← e ← c ← a
 
 ## Best-First Search
 
diff --git a/graph-search/src/features/search/search.js b/graph-search/src/features/search/search.js
index 31b77d22b5cae58d63a29835471891eddb666e4f..86a91cc8b90ef22a0df1eb259c5e2dc70643abb1 100644
--- a/graph-search/src/features/search/search.js
+++ b/graph-search/src/features/search/search.js
@@ -9,33 +9,86 @@ class Edge {
 }
 
 export function dfs(graph, source, destination) {
-  // // SEARCH:
-  // // base case
-  // // initiation
-  // while (…) { // termination condition
-  //   // consecution (part i)
-  //   // action
-  //   if (…) { // early termination conditional
-  //     // POSTPROCESSING:
-  //     // base case
-  //     for(…; // initiation
-  //       …; // termination condition
-  //       …) { // consecution
-  //       // action
-  //     }
-  //     return …;
-  //   }
-  //   // consecution (part ii)
-  // }
-  return undefined; // TODO: stub
+  // SEARCH:
+  const backpointers = new Map();
+  const worklist = [];
+  worklist.push(new Edge(undefined, source));
+  while (worklist.length > 0) {
+    const workitem = worklist.pop();
+    if (backpointers.has(workitem.to)) {
+      continue;
+    }
+    backpointers.set(workitem.to, workitem);
+    if (workitem.to === destination) {
+      // POSTPROCESSING:
+      const reversedPath = [];
+      for (let current = workitem.to;
+        current !== undefined;
+        current = backpointers.get(current).from) {
+        reversedPath.push(current);
+      }
+      return reversedPath.reverse();
+    }
+    for (const incidence of graph.getIncidences(workitem.to)) {
+      worklist.push(new Edge(workitem.to, incidence.destination));
+    }
+  }
+  return undefined;
 }
 
 export function bfs(graph, source, destination) {
-  return undefined; // TODO: stub
+  const backpointers = new Map();
+  const worklist = new Queue();
+  worklist.insert(new Edge(undefined, source));
+  while (worklist.size > 0) {
+    const workitem = worklist.remove();
+    if (backpointers.has(workitem.to)) {
+      continue;
+    }
+    backpointers.set(workitem.to, workitem);
+    if (workitem.to === destination) {
+      const reversedPath = [];
+      for (let current = workitem.to;
+        current !== undefined;
+        current = backpointers.get(current).from) {
+        reversedPath.push(current);
+      }
+      return reversedPath.reverse();
+    }
+    for (const incidence of graph.getIncidences(workitem.to)) {
+      worklist.insert(new Edge(workitem.to, incidence.destination));
+    }
+  }
+  return undefined;
 }
 
 export function dijkstras(graph, source, destination) {
-  return undefined; // TODO: stub
+  const backpointers = new Map();
+  const worklist = new PriorityQueue();
+  worklist.insert(new Edge(undefined, source, 0), 0);
+  while (worklist.size > 0) {
+    const workitem = worklist.remove();
+    if (backpointers.has(workitem.to)) {
+      continue;
+    }
+    backpointers.set(workitem.to, workitem);
+    if (workitem.to === destination) {
+      const reversedPath = [];
+      for (let current = destination;
+        current !== undefined;
+        current = backpointers.get(current).from) {
+        reversedPath.push(current);
+      }
+      return reversedPath.reverse();
+    }
+    for (const incidence of graph.getIncidences(workitem.to)) {
+      worklist.insert(
+        new Edge(workitem.to, incidence.destination, workitem.distance + incidence.weight),
+        workitem.distance + incidence.weight,
+      );
+    }
+  }
+  return undefined;
 }
 
 function heuristic(vertex, destination) {
diff --git a/graph-search/src/features/search/solution.js b/graph-search/src/features/search/solution.js
index 69644f05b7179674513f148f766ecd8ae3c0b252..a64ab4729a95691560c0aae8d3e2fe73cbf91fb3 100644
--- a/graph-search/src/features/search/solution.js
+++ b/graph-search/src/features/search/solution.js
@@ -29,7 +29,7 @@ function formatSolution(solution) {
 }
 
 export function Solution(props) {
-  const search = dfs;
+  const search = dijkstras;
   const firstSolution = search(firstExample, 'a', 'd');
   const secondSolution = search(secondExample, '123', '321');
   return (