Graphs: an illustrated study guide

1. Where graph theory began

A graph is a network of vertices (nodes) joined by edges (links). Graph theory began in 1736, when Leonhard Euler solved the Bridges of Königsberg problem (the city is now Kaliningrad). The city sat on the river Pregel, with an island (Kneiphof) and seven bridges. The question: can you take a walk that crosses every bridge exactly once and returns to where you started?

Königsberg: (a) old map, (b) land masses and bridges, (c) the equivalent graph
(a) the city, (b) land masses A–D and the seven bridges, (c) the abstract graph.
Königsberg bridges as a multigraphCABD
The same graph redrawn. Land masses become vertices, bridges become edges. Two vertices can share more than one edge, so this is a multigraph.

Euler's insight: the shape of the land doesn't matter, only how the pieces connect. Every time you walk through a land mass you use one bridge to enter and another to leave, so each vertex needs an even degree for a closed walk using every edge once to exist.

Land massBridges (degree)Parity
A (Kneiphof island)5odd
B (south bank)3odd
C (north bank)3odd
D (east bank)3odd
All four vertices have odd degree, so no such walk exists. This was the first theorem of graph theory.

2. Vocabulary and types of graphs

Basic terms: a path is a sequence of vertices joined by edges; a cycle is a path that returns to its start. The degree of a vertex is the number of edges incident on it. In a directed graph the degree splits into in-degree (arrows arriving) and out-degree (arrows leaving).

Graphs are classified along several independent axes. A single graph is usually described by combining them, e.g. “a weighted, undirected, connected graph”.

AxisOptionsMeaning
Directiondirected / undirectedDo edges have a direction?
Weightweighted / unweightedDo edges carry a value (cost, distance)?
Connectivityconnected / disconnectedIs there a path between every pair of vertices?
Densitycomplete / incompleteIs every pair of vertices joined by an edge?
Cyclescyclic / acyclicDoes the graph contain a cycle? (mostly discussed for directed graphs)
StructurebipartiteCan the vertices be split into two sets with every edge between them?

Undirected

ABCD

Edges have no direction: A–B is the same as B–A.

Directed (digraph)

ABCD

Edges are one-way arrows, like “follows” on social media.

Weighted

4725ABCD

Each edge carries a number: distance, cost, time.

Connected

ABCD

There is a path between every pair of vertices.

Disconnected

ABCD

Some vertices cannot reach each other (two components).

Complete (K₅)

12345

Every vertex is joined to every other. Kn has n(n−1)/2 edges.

Cyclic

ABCD

Following the arrows you can return to the start (A→B→C→D→A).

Acyclic (DAG)

ABCD

Directed with no cycle. Used for prerequisites and schedules.

Bipartite

123abc

Vertices split into two sets; every edge crosses between them.

3. Bipartite graphs, isomorphism and cliques

Bipartite graphs

A simple graph is bipartite if its vertex set V can be split into two disjoint sets V₁ and V₂ so that every edge joins a vertex of V₁ to a vertex of V₂, and no edge joins two vertices in the same set. The pair (V₁, V₂) is a bipartition.

Colouring test. A graph is bipartite if and only if each vertex can be given one of two colours so that no two adjacent vertices share a colour. In practice: colour the start vertex, run BFS, and give each newly found vertex the opposite colour from its parent. If you ever meet an edge whose ends already have the same colour, the graph is not bipartite. Equivalently, a bipartite graph has no odd-length cycle.

ABCD
A 4-cycle can be 2-coloured, so it is bipartite.
ABC
A triangle (odd cycle) cannot be 2-coloured: the third vertex touches both colours.

Isomorphism

Two graphs are isomorphic if they contain the same number of vertices connected in the same way; one is a re-labelled or re-drawn copy of the other. Quick necessary checks: same number of vertices, same number of edges, and the same vertex degrees. If any differ, the graphs are not isomorphic. Passing all of them does not prove isomorphism.

012345
Graph G: a single 6-cycle.
012345
Graph H: two separate triangles.
CheckG (6-cycle)H (two triangles)
Vertices66
Edges66
Degreesall 2all 2
Connected?yesno
G and H pass the three quick tests but are not isomorphic: G is connected and H is not. The tests can rule isomorphism out, never confirm it.

Cliques

A clique is a subset of vertices in which every vertex is connected to every other, i.e. a complete subgraph. The size of the largest clique is the clique number. Finding the maximum clique is a significant (and computationally hard) problem. In the US-cities graph below, Houston–Dallas–Atlanta form a triangle, a clique of size 3, and no 4-clique exists.

4. Eulerian and Hamiltonian cycles

Two look-alike questions with very different difficulty.

EulerianHamiltonian
Must visitevery edge exactly onceevery vertex exactly once
Cycle / circuitreturns to the starting vertexreturns to the starting vertex
Path versionstart and end at different verticesstart and end at different vertices
TestEasy: all degrees even (and connected) ⇒ Eulerian cycle. For an Euler path: exactly 0 or 2 odd-degree vertices.Hard: no simple degree rule and no known efficient general test.
ExampleKönigsberg: four odd vertices ⇒ impossibleVisiting every town once and coming home
ABCDE
Degrees: A=2, B=3, C=2, D=3, E=2. The highlighted route A→B→C→E→D→A visits every vertex once: a Hamiltonian cycle. But B and D have odd degree, so there is no Eulerian cycle (only an Euler path, from B to D).

5. Representing a graph in a program

Before an algorithm can run, the graph must be stored. There are two standard choices.

123456
Directed example graph (vertices 1–6).

Adjacency matrix

123456
1010000
2000100
3110010
4000001
5010101
6000000

Row = from, column = to. Row 3 reads: 3→1, 3→2, 3→5.

Adjacency lists

VertexAdjacency list
12
24
31 → 2 → 5
46
52 → 4 → 6
6∅

Undirected graphs give a symmetric matrix

ABCDE
ABCDE
A01010
B10110
C01001
D11001
E00110

Every edge appears twice (A–B sets both [A][B] and [B][A]), so the matrix equals its own transpose.

Which one to choose?

Adjacency matrixAdjacency list
MemoryO(V²)O(V + E)
Is there an edge u→v?O(1)O(degree of u)
List all neighbours of uO(V)O(degree of u)
Best fordense graphs, frequent edge look-upssparse graphs, traversals

Most real graphs (road maps, social networks) are sparse, so adjacency lists are the usual default.

6. Graph traversals: DFS and BFS

A traversal visits every vertex reachable from a starting vertex exactly once. The two classic strategies differ only in the data structure that remembers where to go next: a stack (last in, first out) gives depth-first search, a queue (first in, first out) gives breadth-first search. When several neighbours are available, they are taken in alphabetical order.

Depth-first search (DFS)

  1. Create a stack.
  2. Pick a start vertex, make it current, mark it visited, push it.
  3. If the current vertex has an unvisited neighbour (in order), visit it: make it current, mark it, push it.
  4. Otherwise pop a vertex off the stack and make it current.
  5. Repeat 3–4 until the stack is empty.

DFS plunges as deep as it can, then backtracks. Good for cycle detection, connected components, topological sort and maze solving.

Breadth-first search (BFS)

  1. Create a queue.
  2. Pick a start vertex, make it current, mark it visited.
  3. Visit each unvisited neighbour of the current vertex in order: mark it and enqueue it.
  4. When none remain, dequeue a vertex and make it current.
  5. Repeat 3–4 until the queue is empty.

BFS explores in rings of increasing distance from the start. It finds the path with the fewest edges in an unweighted graph.

Try it: step through both on the same tree

ABCDEFGHI

DFS from A. Blue = current, green = on the stack, grey = finished.
ABCDEFGHI

BFS from A. Blue = current, green = discovered, grey = finished.

DFS trace

EventStack
Start: visit A, mark it visited, push it on the stack.A
Visit B: an unvisited neighbour of A. Mark it and push it.A B
Visit F: an unvisited neighbour of B. Mark it and push it.A B F
Visit H: an unvisited neighbour of F. Mark it and push it.A B F H
H has no unvisited neighbours: pop it. F becomes current.A B F
F has no unvisited neighbours: pop it. B becomes current.A B
B has no unvisited neighbours: pop it. A becomes current.A
Visit C: an unvisited neighbour of A. Mark it and push it.A C
C has no unvisited neighbours: pop it. A becomes current.A
Visit D: an unvisited neighbour of A. Mark it and push it.A D
Visit G: an unvisited neighbour of D. Mark it and push it.A D G
Visit I: an unvisited neighbour of G. Mark it and push it.A D G I
I has no unvisited neighbours: pop it. G becomes current.A D G
G has no unvisited neighbours: pop it. D becomes current.A D
D has no unvisited neighbours: pop it. A becomes current.A
Visit E: an unvisited neighbour of A. Mark it and push it.A E
E has no unvisited neighbours: pop it. A becomes current.A
A has no unvisited neighbours: pop it. Stack empty: done.—

BFS trace

EventQueue
Start: visit A and mark it. A is the current vertex.—
Visit B, a neighbour of A. Mark it and enqueue it.B
Visit C, a neighbour of A. Mark it and enqueue it.B C
Visit D, a neighbour of A. Mark it and enqueue it.B C D
Visit E, a neighbour of A. Mark it and enqueue it.B C D E
No more unvisited neighbours: dequeue B and make it current.C D E
Visit F, a neighbour of B. Mark it and enqueue it.C D E F
No more unvisited neighbours: dequeue C and make it current.D E F
No more unvisited neighbours: dequeue D and make it current.E F
Visit G, a neighbour of D. Mark it and enqueue it.E F G
No more unvisited neighbours: dequeue E and make it current.F G
No more unvisited neighbours: dequeue F and make it current.G
Visit H, a neighbour of F. Mark it and enqueue it.G H
No more unvisited neighbours: dequeue G and make it current.H
Visit I, a neighbour of G. Mark it and enqueue it.H I
No more unvisited neighbours: dequeue H and make it current.I
No more unvisited neighbours: dequeue I and make it current.—
I is finished and the queue is empty: done.—

Result: DFS order A, B, F, H, C, D, G, I, E; BFS order A, B, C, D, E, F, G, H, I. Both visit every vertex and take O(V + E) time with an adjacency list.

DFSBFS
Data structurestack (or recursion)queue
Shape of explorationdeep, then backtracklevel by level
Shortest path (unweighted)not guaranteedguaranteed
TimeO(V + E)O(V + E)

7. Case study: a graph of US cities

Your 14 Nov lecture modelled 12 US cities as a graph and stored it as text (graph.txt). The file format is: the number of vertices (12), the city names (vertices 0–11), the number of edge entries (46), then one line per entry from to weight, followed by some test queries (Houston; Dallas → Atlanta; Denver). Every road appears in both directions with weight 1, so the graph is undirected and unweighted with 46 / 2 = 23 edges.

01234567891011SeattleSan FranciscoLos AngelesDenverKansas CityChicagoBostonNew YorkAtlantaMiamiDallasHouston
The 12-city graph rebuilt from graph.txt; positions approximate your “Modeling Using Graphs” map.

Adjacency list built from the file

CityNeighbours
SeattleSan Francisco, Denver, Chicago
San FranciscoSeattle, Los Angeles, Denver
Los AngelesSan Francisco, Denver, Kansas City, Dallas
DenverSeattle, San Francisco, Los Angeles, Kansas City, Chicago
Kansas CityLos Angeles, Denver, Chicago, New York, Atlanta, Dallas
ChicagoSeattle, Denver, Kansas City, Boston, New York
BostonChicago, New York
New YorkKansas City, Chicago, Boston, Atlanta
AtlantaKansas City, New York, Miami, Dallas, Houston
MiamiAtlanta, Houston
DallasLos Angeles, Kansas City, Atlanta, Houston
HoustonAtlanta, Miami, Dallas

Traversals starting from Houston

BFS order: Houston, Atlanta, Miami, Dallas, Kansas City, New York, Los Angeles, Denver, Chicago, Boston, San Francisco, Seattle.
DFS order: Houston, Atlanta, Kansas City, Los Angeles, San Francisco, Seattle, Denver, Chicago, Boston, New York, Dallas, Miami.
Neighbours are taken in vertex-number order, so the results depend on that numbering.

Fewest-stops route from Dallas to Atlanta (a BFS query): Dallas → Atlanta (1 edge). From Houston to Denver: Houston → Atlanta → Kansas City → Denver (3 edges).

8. Measuring a graph

Metrics answer two questions: how well connected is the whole graph? and which vertices matter most? The right-hand column applies each metric to the US-cities graph (V = 12, E = 23).

MetricDefinitionUS cities graph
Edge densityactual edges ÷ maximum possible edges, V(V−1)/2 for undirected23/66 = 0.348
Node connectivityminimum number of vertices whose removal disconnects the graph (or leaves a single vertex)2 (removing Chicago and New York cuts Boston off)
Algebraic connectivitysecond-smallest eigenvalue of the graph Laplacian L = D − A. It is greater than 0 iff the graph is connected; larger means more robustly connected0.758 (positive, so connected)
Degree centralityneighbours ÷ neighbours possible in a complete graph (V−1). Directed graphs: in-degree (“followers”) and out-degree (“following”)Kansas City highest: 6/11 = 0.55
Betweenness centralityfor each vertex v, sum over all pairs (s,t) of (shortest s–t paths through v) ÷ (all shortest s–t paths). High values mark “gatekeepers” or bridgesKansas City highest (14.6)
Clique numbersize of the largest complete subgraph3 (Houston–Dallas–Atlanta)

Degree and betweenness for each city

CityDegreeDegree centralityBetweenness
Kansas City66/11 = 0.5514.6
Atlanta55/11 = 0.4512.7
Chicago55/11 = 0.459.0
New York44/11 = 0.366.6
Dallas44/11 = 0.366.1
Denver55/11 = 0.456.0
Los Angeles44/11 = 0.365.8
Seattle33/11 = 0.271.2
Houston33/11 = 0.271.1
San Francisco33/11 = 0.270.9
Boston22/11 = 0.180.0
Miami22/11 = 0.180.0

Boston and Miami have betweenness 0: each connects only to cities already linked to each other, so no shortest path needs to pass through them. Kansas City is both well connected and a hub that many shortest routes cross.

9. Dijkstra's shortest-path algorithm

For a weighted graph with non-negative weights, the shortest path is the one with the lowest total weight, not the fewest edges. Dijkstra's algorithm finds the cheapest route from one start vertex to every other vertex.

  1. Give the start vertex cost 0 and every other vertex cost ∞.
  2. Visit the unvisited vertex with the cheapest known cost from the start.
  3. From it, update each neighbour: if (cost to here + edge weight) beats the neighbour's current cost, record the new cost and remember “via” this vertex.
  4. Repeat 2–3 until all reachable vertices are visited.

In short: visit the vertex with the cheapest path from the start, and update the cheapest fares from there. A vertex is final once visited, which is why negative weights break the method.

5080609050207040ABCDE

Dijkstra from A. Numbers under each node are the best known cost. Blue = being visited, grey = finalised, thick edges = current shortest-path tree.

Table from your notes (recomputed)

StepBCDE
Visit A (cheapest unvisited, cost 0).50 via A∞80 via A∞
Visit B (cheapest unvisited, cost 50).50 via A110 via B80 via A∞
Visit D (cheapest unvisited, cost 80).50 via A100 via D80 via A150 via D
Visit C (cheapest unvisited, cost 100).50 via A100 via D80 via A140 via C
Visit E (cheapest unvisited, cost 140).50 via A100 via D80 via A140 via C
Final result from A: B = 50 (A→B), D = 80 (A→D), C = 100 (A→D→C), E = 140 (A→D→C→E). C is first reached at 110 via B, then improved to 100 via D: the “update” step in action.

Complexity: O(V²) with a plain array; O((V + E) log V) with a priority queue (heap).

10. Directed acyclic graphs and topological sort

A DAG is a directed graph with no cycles. It naturally models dependencies: course prerequisites, build steps, task schedules. A topological sort lists the vertices so that for every edge u→v, u appears before v. It exists only for DAGs (a cycle would make some vertex its own prerequisite).

ABCDEF
Example DAG. Think of A as “do first” and F as “do last”.

Algorithm (as in your notes)

  1. Compute the in-degree (number of incoming edges) of every vertex.
  2. Take all vertices with in-degree 0, sort them, and enqueue them. Remove them from the graph, which lowers the in-degree of their successors.
  3. Repeat step 2 until the graph is empty. (If vertices remain but none has in-degree 0, there is a cycle.)
  4. Dequeue the vertices and print them.
RoundIn-degrees of remaining verticesRemoved (in-degree 0)
1A=0, B=1, C=1, D=2, E=1, F=2A
2B=0, C=0, D=2, E=1, F=2B, C
3D=0, E=0, F=2D, E
4F=0F
Topological order: A → B → C → D → E → F. The answer is not always unique (B and C could be swapped, as could D and E). Sorting each round fixes one canonical answer.

11. Minimum spanning tree (Kruskal and Prim)

A spanning tree of a connected, weighted, undirected graph connects all V vertices using exactly V−1 edges and no cycles. The minimum spanning tree (MST) is the one with the smallest total weight, e.g. the cheapest cable network linking every office. Two greedy algorithms build it.

Kruskal: pick the globally cheapest edges

  1. Sort all edges by increasing weight.
  2. Start with the vertices and no edges.
  3. Take the next edge; add it unless it forms a cycle.
  4. Stop when all vertices are connected.

Prim: grow one tree outward

  1. Start with any vertex in the “visited” set.
  2. Pick the cheapest edge from a visited vertex to an unvisited one.
  3. Add that edge and vertex.
  4. Stop when all vertices are visited.

The example is the 8-vertex graph from your MST worksheet. Both algorithms reach the same tree here, with total weight 1.99. In general, ties can give different trees of equal weight.

0.310.630.140.350.300.540.310.470.130.540.430.540.540.620.3723514076

Kruskal. Thick blue edges are in the tree; red dashed edges were rejected.
0.310.630.140.350.300.540.310.470.130.540.430.540.540.620.3723514076

Prim starting at vertex 0. Grey nodes are in the visited set.

Kruskal's edge order

EdgeWeightDecisionRunning total
7–30.13add0.13
2–00.14add0.27
4–10.30add0.57
2–30.31add0.88
1–70.31add1.19
1–30.35skip (cycle)
5–60.37add1.56
3–50.43add1.99

Prim's choices (start 0)

Edge addedWeightRunning total
0–20.140.14
2–30.310.45
3–70.130.58
7–10.310.89
1–40.301.19
3–50.431.62
5–60.371.99
MST edges: 7–3, 2–0, 4–1, 2–3, 1–7, 5–6, 3–5. Total = 1.99.
KruskalPrim
Strategyadd cheapest edge anywhere that makes no cycleadd cheapest edge leaving the current tree
Needssorted edge list + cycle check (union-find)priority queue of frontier edges
TimeO(E log E)O(E log V) with a heap
Tends to suitsparse graphsdense graphs

12. Modelling a puzzle as a graph

Graphs are not only for maps. Any problem made of states and moves becomes a graph: each state is a vertex, each legal move is an edge. Solving the puzzle then means finding a path from the start state to the goal state, which is exactly what BFS does.

Farmer, Wolf, Goat, Cabbage. The farmer must ferry all three across a river in a boat that holds him plus one item. Left alone, the wolf eats the goat and the goat eats the cabbage. Each vertex shows (left bank | right bank), with F = farmer, W = wolf, G = goat, C = cabbage. Unsafe states are simply left out of the graph.

FWGC | –WC | FGFWC | GW | FGCFWG | CC | FWGFGC | WG | FWCFG | WC– | FWGC
Safe states from your notes. The two branches in the middle are the two equally short solutions (carry the wolf or the cabbage). Either takes 7 crossings.

Reading the path: take the goat across, return alone, take the wolf (or cabbage), bring the goat back, take the cabbage (or wolf), return alone, take the goat. The diamond is where the two solutions split and rejoin.

13. Cheat sheet

ProblemAlgorithmKey ideaTime
Visit everything, go deepDFSstack, backtrackO(V + E)
Fewest edges / level orderBFSqueue, rings outwardO(V + E)
Cheapest path (weights ≥ 0)Dijkstraalways finalise the cheapest unvisited vertexO((V+E) log V)
Order tasks with dependenciesTopological sortrepeatedly remove in-degree-0 verticesO(V + E)
Cheapest network joining all verticesKruskal / Primgreedy, never form a cycleO(E log E) / O(E log V)
2-colourabilityBFS colouringalternate colours level by levelO(V + E)
ConceptOne-line summary
Degreenumber of edges at a vertex (in/out for directed graphs)
Eulerian cycleevery edge once; needs all degrees even
Hamiltonian cycleevery vertex once; no simple test
Adjacency matrix / listO(V²) space, fast edge test / O(V+E) space, fast neighbour scan
Edge densityedges ÷ V(V−1)/2
Node connectivityfewest vertices whose removal disconnects the graph
Algebraic connectivitysecond-smallest Laplacian eigenvalue; > 0 iff connected
Degree / betweenness centralityhow many neighbours / how many shortest paths pass through
Cliquecomplete subgraph; clique number = size of the largest

Time complexities and the Euler-path and bipartite tests are standard results added to round out your notes. Everything else comes from your lecture notes and worksheets.