Chapter 14: Graphs
Short Answer · Basic Terms
Question 1: Degrees and the Handshaking Lemma
In the undirected graph V = {0, 1, 2, 3, 4}, E = {(0,1), (0,4), (1,2), (1,3), (1,4), (2,3), (3,4)}, find the degree of every vertex and verify the handshaking lemma (Σ deg(v) = 2m).
Show answer
| v | 0 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|---|
| deg(v) | 2 | 4 | 2 | 3 | 3 |
Σ deg = 2 + 4 + 2 + 3 + 3 = 14 = 2 · 7 (m = 7). Each edge adds one to the degree of both its ends, so the total is always twice the number of edges.
Consequence: the number of odd-degree vertices (here 3 and 4) is always even.
Multiple Choice · Basic Terms
Question 2: Is This Degree Sequence Possible?
Can a simple undirected graph have vertex degrees 3, 3, 2, 2, 1?
The total, 11, is odd; by the handshaking lemma it must equal 2m, which would require 11 / 2 = 5.5 edges. A is tempting, but no such graph exists; the condition in B is necessary but not sufficient.
Multiple Choice · Basic Terms
Question 3: Kinds of Paths
In the undirected graph V = {1, …, 5}, E = {(1,2), (1,3), (1,4), (2,5), (3,4), (4,5)}, which of these is a path that is not simple?
All its edges (1–4, 4–3, 3–1, 1–2) exist, but 1 appears twice → a path, but not a simple one. B and C are simple paths (the edges exist and no vertex repeats); D is not a path at all, since there is no edge 5–3.
Multiple Choice · Basic Terms
Question 4: Directed Edges and Adjacency
A digraph has the edge (u, v) but not (v, u). Which statement is certainly true?
u is the tail (origin) and v the head (destination); adjacency is directed. C is tempting but wrong: there may be a path from v to u through other vertices (v → w → u). D: this edge adds to u's out-degree.
Short Answer · Graph Representations
Question 5: The Adjacency Matrix of a Digraph
Write the adjacency matrix of the digraph with edges A→B, A→D, B→C, C→A, D→C, D→E, E→B. How do you read A's out-degree and C's in-degree from the matrix?
Show answer
| A | B | C | D | E | |
|---|---|---|---|---|---|
| A | 0 | 1 | 0 | 1 | 0 |
| B | 0 | 0 | 1 | 0 | 0 |
| C | 1 | 0 | 0 | 0 | 0 |
| D | 0 | 0 | 1 | 0 | 1 |
| E | 0 | 1 | 0 | 0 | 0 |
Row = origin, column = destination. A's out-degree = the sum of row A = 2; C's in-degree = the sum of column C = 2 (B→C, D→C).
The matrix is not symmetric (e.g. A→B exists, B→A does not). Memory O(n²) = 25 cells, only 7 of them 1.
Multiple Choice · Graph Representations
Question 6: Empty Cells in a Weighted Matrix
In the adjacency matrix of a weighted graph, why do cells with no edge hold ∞ (e.g. Integer.MAX_VALUE) rather than 0?
A 0 in an edgeless cell means a fake, free edge (a 0 on the diagonal does make sense, as the distance to itself). B has it backwards: Java already initializes int[][] to 0, which is exactly why ∞ must be filled in explicitly.
Short Answer · Graph Representations
Question 7: Adjacency Lists After addEdge
Using the Graph class from the slides (undirected addEdge), write the contents of the five neighbor lists, in insertion order, after this code runs.
Graph g = new Graph(5); int[][] E = {{2,0}, {0,3}, {3,1}, {1,4}, {2,3}, {4,3}}; for (int[] e : E) g.addEdge(e[0], e[1]); // addEdge(u, v): // adj.get(u).add(v); // adj.get(v).add(u);
Show answer
0: [2, 3] · 1: [3, 4] · 2: [0, 3]
3: [0, 1, 2, 4] · 4: [1, 3]
Each edge goes into two lists → 6 edges, 12 entries (= 2m). A list's length is the degree: degree(3) = 4.
The lists are not sorted; their order is insertion order, and the visit order of BFS/DFS depends on it. Each addEdge is O(1); memory O(n + m).
Multiple Choice · Graph Representations
Question 8: The Cost of getEdge
In an undirected graph, what does the Graph ADT operation getEdge(u, v) ("Is there an edge u–v?") cost with an edge list, an adjacency list, and an adjacency matrix, respectively?
The edge list scans every edge; with adjacency lists we scan the shorter list; the matrix reads the single cell m[u][v]. C is tempting, but a matrix query does not scan a row: the O(n) row scan is the cost of "visit the neighbors".
Short Answer · Graph Representations
Question 9: Choosing a Representation for a Road Network
Would you store a road network of n = 10⁵ intersections and m = 3 · 10⁵ two-way roads as an adjacency matrix or as adjacency lists? Justify your choice by comparing the memory needed, with numbers.
Show answer
Adjacency lists.
- Matrix: n² = 10¹⁰ cells (≈ 10 GB even at 1 byte per cell); only 2m = 6 · 10⁵ cells are filled → 0.006%.
- Lists: n lists + 2m = 6 · 10⁵ entries → O(n + m) ≈ 7 · 10⁵ items, a few MB.
The graph is sparse (m ≈ 3n). Traversal also takes O(n + m) with lists but O(n²) with a matrix. A matrix pays off for dense graphs (m ≈ n²) and frequent "Is there an edge?" queries.
Short Answer · Traversal (BFS / DFS)
Question 10: A Faulty BFS: Where Is the Mark?
This BFS marks a vertex when it leaves the queue, not when it enters. On the triangle with edges 0–1, 0–2, 1–2 (neighbors in increasing order), what does bfs(0) print?
void bfs(int s) { boolean[] visited = new boolean[n]; Queue<Integer> q = new ArrayDeque<>(); q.add(s); while (!q.isEmpty()) { int w = q.poll(); visited[w] = true; // marked here System.out.print(w + " "); for (int u : adj.get(w)) if (!visited[u]) q.add(u); } }
Show answer
Output: 0 1 2 2
- 0 leaves → 1 and 2 are added: q = [1, 2].
- 1 leaves → 2 is not yet marked, so it is added again: q = [2, 2].
- 2 leaves twice and is printed twice.
Fix: mark a vertex as it enters the queue (visited[u] = true; q.add(u);, and visited[s] = true at the start). Then each vertex enters the queue once; otherwise the queue can grow to O(m).
Code Trace · Traversal (BFS / DFS)
Question 11: BFS Order
The neighbor lists are 0: [2, 4] · 1: [3, 5] · 2: [0, 3] · 3: [1, 2, 5] · 4: [0, 5] · 5: [1, 3, 4]. In what order does bfs(0) print the vertices?
0 is marked as it enters the queue.
0 leaves the queue and is printed; its neighbors are 2, 4.
2 and 4 are marked and enqueued (level 1).
2 leaves; its neighbors are 0, 3.
0 is already marked → skip; 3 is added (level 2).
4 leaves; its neighbors are 0, 5.
0 is skipped; 5 is added (level 2).
3 leaves; its neighbors are 1, 2, 5.
1 is added (level 3); 2 and 5 are already marked.
5 leaves; its neighbors 1, 3, 4 are all marked → nothing added.
1 leaves; its neighbors 3, 5 are marked.
The queue is empty → done. Levels: {0}, {2, 4}, {3, 5}, {1}. O(n + m).
void bfs(int s) { boolean[] visited = new boolean[n]; Queue<Integer> q = new ArrayDeque<>(); visited[s] = true; q.add(s); while (!q.isEmpty()) { int w = q.poll(); System.out.print(w + " "); for (int u : adj.get(w)) if (!visited[u]) { visited[u] = true; q.add(u); } } }
Multiple Choice · Traversal (BFS / DFS)
Question 12: Recursive DFS Order
On this graph, whose neighbor lists are in alphabetical order, in what order does the recursive dfs(H) print the vertices?
A: B F I B: A C E C: B D E D: C G H E: B C G F: A G G: D E F H: D I: A
H → D → C → B → A (at each step, the first unvisited neighbor alphabetically) → F → G → E; at the dead end DFS backs up and goes from A to I. A is tempting, but it is the BFS order (level by level). D picks E instead of A after B.
Short Answer · Traversal (BFS / DFS)
Question 13: Connected Components
With n = 8 and edges (0,4), (4,6), (1,2), (5,7), (7,3), what are the array comp[] and the return value after calling components(comp)?
int components(int[] comp) { Arrays.fill(comp, -1); int count = 0; for (int s = 0; s < n; s++) if (comp[s] == -1) dfs(s, count++, comp); return count; } void dfs(int v, int c, int[] comp) { comp[v] = c; for (int u : adj.get(v)) if (comp[u] == -1) dfs(u, c, comp); }
Show answer
comp = [0, 1, 1, 2, 0, 2, 0, 2], return value 3.
- s = 0: dfs {0, 4, 6} → component 0.
- s = 1: dfs {1, 2} → component 1.
- s = 2: already labeled. s = 3: dfs {3, 7, 5} → component 2 (3 comes before 5).
Now "Are u and v in the same component?" is the O(1) test comp[u] == comp[v]. Total O(n + m).
Multiple Choice · Traversal (BFS / DFS)
Question 14: Bipartite Graphs
Which of these graphs is bipartite (2-colorable by BFS)?
Bipartite ⇔ no odd-length cycle. In C6 the colors run 0, 1, 0, 1, 0, 1, and the closing edge also joins opposite colors. B is tempting, but C5 has odd length: BFS finds two adjacent vertices of the same color → false. K4 contains a triangle.
Code Trace · Traversal (BFS / DFS)
Question 15: Topological Sorting with Kahn
For the DAG with adj: 0: [] · 1: [] · 2: [3] · 3: [1] · 4: [0, 1] · 5: [2, 0], what order does kahn(adj) return?
Count the in-degrees: 0 ← 4, 5 · 1 ← 3, 4 · 2 ← 5 · 3 ← 2.
4 and 5, with in-degree 0, enter the queue: they depend on nothing.
4 leaves and joins the result.
4→0 and 4→1 count as deleted; 0 and 1 each still wait for one prerequisite.
5 leaves and joins the result.
5→2: indeg[2] = 0 → enqueue 2; 5→0: indeg[0] = 0 → enqueue 0.
2 leaves and joins the result.
2→3: indeg[3] = 0 → enqueue 3.
0 leaves; its list is empty, so nothing is updated.
3 leaves and joins the result.
3→1: indeg[1] = 0 → enqueue 1.
1 leaves and joins the result.
The queue is empty. Size 6 = n → no cycle. Order: 4 5 2 0 3 1. O(n + m).
List<Integer> kahn(List<List<Integer>> adj) {
int n = adj.size();
int[] indeg = new int[n];
for (List<Integer> l : adj)
for (int v : l) indeg[v]++;
Queue<Integer> q = new ArrayDeque<>();
for (int v = 0; v < n; v++)
if (indeg[v] == 0) q.add(v);
List<Integer> result = new ArrayList<>();
while (!q.isEmpty()) {
int u = q.poll();
result.add(u);
for (int v : adj.get(u))
if (--indeg[v] == 0) q.add(v);
}
return result; // size < n → cycle
}
Short Answer · Traversal (BFS / DFS)
Question 16: Faulty Cycle Detection
The line color[v] = 2 has been forgotten. For the DAG with edges 0→1, 0→2, 1→2, what does hasCycle(0, color) return, and why?
// color: 0 white, 1 gray, 2 black boolean hasCycle(int v, int[] color) { color[v] = 1; for (int u : adj.get(v)) { if (color[u] == 1) return true; if (color[u] == 0 && hasCycle(u, color)) return true; } // color[v] = 2; (forgotten) return false; }
Show answer
It returns true: a false alarm, since there is no cycle.
- 0 gray → 1 gray → 2 gray; 2 has no outgoing edges and returns false, but 2 stays gray. So does 1.
- Back at 0, edge 0→2 finds color[2] == 1 → mistaken for a back edge.
The correct rule: a finished vertex turns black (2). Only an edge to a gray vertex (one on the current path) means a cycle; an edge to a black vertex does not. The fixed code returns false.
Multiple Choice · Shortest Paths
Question 17: BFS on a Weighted Graph
In this weighted digraph, what is the weighted length of the path from A to F that BFS finds (neighbors in alphabetical order)?
A→B 4 A→C 2 B→C 5 B→D 10 C→E 3 E→D 4 D→F 11
BFS finds the path with the fewest edges: A→B→D→F (3 edges) = 4 + 10 + 11 = 25. A is tempting, but 20 is the length of the true shortest path A→C→E→D→F (Dijkstra's answer). C is the number of edges, not the weight.
Short Answer · Shortest Paths
Question 18: Running Dijkstra by Hand
Run Dijkstra from A on this weighted undirected graph. Find each vertex's shortest distance and its prev[] value. In what order are the vertices settled?
Show answer
| A | B | C | D | E | F | G | |
|---|---|---|---|---|---|---|---|
| d | 0 | 3 | 2 | 8 | 10 | 13 | 14 |
| prev | – | C | A | B | D | E | F |
Settling order: A C B D E F G
- Once C = 2 is settled, B drops from 4 to 2 + 1 = 3.
- D = 3 + 5 = 8 (better than A–C–D = 10); E = 8 + 2 = 10 (12 via C–E).
- F = 10 + 3 = 13 (14 via D–F); G = 13 + 1 = 14 (17 via E–G).
Multiple Choice · Shortest Paths
Question 19: The Stale-Entry Check
In the Java Dijkstra, what happens if the marked continue line is deleted (weights ≥ 0)?
long[] e = pq.poll(); int u = (int) e[0]; if (e[1] > d[u]) continue; // stale for (int[] k : adj.get(u)) { int v = k[0]; long alt = d[u] + k[1]; if (alt < d[v]) { d[v] = alt; pq.add(new long[]{v, alt}); } }
When a stale entry comes out, d[u] is already smaller and the neighbors were relaxed with that d[u] earlier; alt < d[v] cannot hold again. A is tempting, but the line is there for efficiency, not correctness (stale entries are the duplicates added because Java's PQ has no "decrease key").
Short Answer · Minimum Spanning Trees
Question 20: An MST with Kruskal
Find the graph's minimum spanning tree (MST) with Kruskal's algorithm. List the edges in the order they are chosen and give the total weight. After which edge does the algorithm stop?
Show answer
| Edge | w | find(u) ≠ find(v)? | Decision |
|---|---|---|---|
| E–F | 1 | yes | accept |
| B–D | 2 | yes | accept |
| A–C | 3 | yes | accept |
| C–E | 4 | yes | accept |
| B–C | 5 | yes | accept → |T| = 5 = n − 1 |
Total weight 1 + 2 + 3 + 4 + 5 = 15. After B–C, |T| = n − 1, so the algorithm stops; A–B (6), C–D (7), D–E (8), and D–F (9) are never examined. Had it been examined, A–B would be rejected: A and B are already in the same set via A–C–B (a cycle).
Union-Find answers "Would this edge form a cycle?" in nearly constant time by comparing find(u) == find(v).
Multiple Choice · Minimum Spanning Trees
Question 21: The Cost of Kruskal's Algorithm
For a graph with n vertices and m edges, which phase determines the total running time of Kruskal's algorithm implemented with Union-Find?
2m finds + (n − 1) unions cost only O(m · α(n)), nearly linear; sorting dominates. Since m ≤ n², log m ≤ 2 log n, so O(m log m) = O(m log n). B is tempting, but it would apply only if cycles were checked with DFS instead of Union-Find.
Short Answer · Minimum Spanning Trees
Question 22: An MST with Prim
Run Prim's algorithm on the graph in the figure, starting from A. List the edges in the order they join the tree and give the total weight. How does the result compare with the tree Kruskal's algorithm found?
Show answer
| Step | Tree | Lightest outgoing edge |
|---|---|---|
| 1 | A | A–C 3 |
| 2 | A, C | C–E 4 |
| 3 | A, C, E | E–F 1 |
| 4 | A, C, E, F | C–B 5 |
| 5 | A, B, C, E, F | B–D 2 |
Total 3 + 4 + 1 + 5 + 2 = 15: the same edges as Kruskal, in a different order. Prim can see E–F (1) only once E joins the tree; Kruskal picks it first.
Multiple Choice · Minimum Spanning Trees
Question 23: Prim's Choice
Which edge does Prim's algorithm add to the tree at each step?
One end of the edge must be in the tree and the other outside; the lightest such edge is chosen. A is Kruskal's rule (with a cycle check). B is Dijkstra's key. D is wrong: the lightest outgoing edge may leave from a vertex added earlier.
Multiple Choice · Minimum Spanning Trees
Question 24: Stale Entries
In lazy Prim with a priority queue, what happens if the line if (inTree[e[1]]) continue; is deleted?
After v joins the tree, old entries leading to v stay in the queue. Without the check, when such an entry comes out, an edge with both ends in the tree is added to T: a cycle forms and the spanning tree is ruined.
Short Answer · Shortest Paths
Question 25: Dijkstra with a Negative Edge
Run the pseudocode Dijkstra from the slides (a vertex removed from Q is settled; only neighbors still in Q are relaxed) from A on this digraph. What distances does it find, what are the correct distances, and at which step does the error begin?
A→B 2 A→C 4 C→B −3 B→D 1
Show answer
| Removed | d[B] | d[C] | d[D] |
|---|---|---|---|
| A (0) | 2 | 4 | ∞ |
| B (2) | 2 | 4 | 3 |
| D (3) | 2 | 4 | 3 |
| C (4) | 2 | 4 | 3 |
Dijkstra: B = 2, C = 4, D = 3. Correct: B = 4 − 3 = 1 (A→C→B), D = 2 (A→C→B→D).
The error begins when B is settled at 2: the assumption that "the smallest distance in the queue cannot be beaten by another route" holds only when weights are ≥ 0. When C is processed, B is no longer in Q, so C→B (−3) is never relaxed, and the wrong d[B] spreads to D.
The Java version with stale entries would re-add B to the queue here and find the right answer, but it loses its time bound. With negative edges, use Bellman-Ford.
Short Answer · Shortest Paths
Question 26: Distances and Paths with BFS
The adjacency lists of an undirected graph are given below in scanning order. The unweighted shortest-path algorithm runs from 0: if dist[u] == INF, it sets dist[u] = dist[w] + 1 and prev[u] = w and enqueues u. What are dist[], prev[], and path(prev, 0, 6)?
0: 1, 2 4: 1, 2, 5 1: 0, 3, 4 5: 3, 4, 6 2: 0, 4 6: 5 3: 1, 5 7: (no neighbors)
Show answer
| v | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|---|
| dist | 0 | 1 | 1 | 2 | 2 | 3 | 4 | ∞ |
| prev | −1 | 0 | 0 | 1 | 1 | 3 | 5 | −1 |
Dequeue order: 0, 1, 2, 3, 4, 5, 6. Vertex 4 can also be reached through 2, but 1 leaves the queue first, so prev[4] = 1; 3 reaches 5 first. 7 is never reached.
path: trace back 6 → 5 → 3 → 1 → 0 and reverse it with addFirst: [0, 1, 3, 5, 6], 4 edges = dist[6]. 0 → 2 → 4 → 5 → 6 also has 4 edges; the neighbor order decides which one is found. Total O(n + m).
Multiple Choice · Shortest Paths
Question 27: What Does path() Return?
A BFS has produced prev = [−1, 0, 0, 1, 1, 3, 5, −1]. With this array, what do path(prev, 0, 7) and path(prev, 2, 6) return?
List<Integer> path(int[] prev, int s, int t) { LinkedList<Integer> p = new LinkedList<>(); for (int v = t; v != -1; v = prev[v]) p.addFirst(v); if (p.getFirst() != s) return List.of(); return p; }
t = 7: p = [7], and prev[7] = −1 ends the loop; the first element 7 ≠ 0 → empty list (unreachable). s = 2, t = 6: the chain is 6, 5, 3, 1, 0; the first element 0 ≠ 2 → again an empty list. C is tempting: there is a 3-edge path from 2 to 6, but prev[] is the path tree from source 0; a path from 2 needs a fresh BFS from 2. B gives the lists returned without the first-element check. D is wrong: since the condition is v != -1, prev[−1] is never read.