Chapter 14: Graphs

Chapter 14: Graphs · Study Questions
Basic termsGraph representationsBFS and DFSComponents and topological sortingUnweighted shortest pathsDijkstraKruskal and Prim
Sercan KÜLCÜ · Giresun University · Computer Engineering

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
v01234
deg(v)24233

Σ 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
ABCDE
A01010
B00100
C10000
D00101
E01000

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?

012345
012345

0 is marked as it enters the queue.

012345

0 leaves the queue and is printed; its neighbors are 2, 4.

012345

2 and 4 are marked and enqueued (level 1).

012345

2 leaves; its neighbors are 0, 3.

012345

0 is already marked → skip; 3 is added (level 2).

012345

4 leaves; its neighbors are 0, 5.

012345

0 is skipped; 5 is added (level 2).

012345

3 leaves; its neighbors are 1, 2, 5.

012345

1 is added (level 3); 2 and 5 are already marked.

012345

5 leaves; its neighbors 1, 3, 4 are all marked → nothing added.

012345

1 leaves; its neighbors 3, 5 are marked.

012345

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?

421581026317ABCDEFG
Show answer
ABCDEFG
d0328101314
prev–CABDEF

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?

635274891ABCDEF
Show answer
Edgewfind(u) ≠ find(v)?Decision
E–F1yesaccept
B–D2yesaccept
A–C3yesaccept
C–E4yesaccept
B–C5yesaccept → |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?

635274891ABCDEF
Show answer
StepTreeLightest outgoing edge
1AA–C 3
2A, CC–E 4
3A, C, EE–F 1
4A, C, E, FC–B 5
5A, B, C, E, FB–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
Removedd[B]d[C]d[D]
A (0)24∞
B (2)243
D (3)243
C (4)243

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
v01234567
dist0112234∞
prev−1001135−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.

The End

Chapter 14: Graphs: Study Questions
Lecture slides: Chapter 14: Graphs
1 / 1 Sercan KÜLCÜ. All rights reserved.