AnyLearn
All lessons
Mathintermediate

Graphs: A Language for Relationships

A graph is two sets and an incidence relation, and that austerity is why the same object models build dependencies, social networks, register allocation and road maps. This lesson covers the structural properties worth knowing, the special families that make hard problems easy, and the line where a small change to a question makes it intractable.

Updated · AI-authored, review-gated · how lessons are made

Not signed in: your progress and quiz score won't be saved.
Progress1 / 10

Two sets and a relation

A graph G=(V,E)G = (V, E) is a set of vertices and a set of edges joining pairs of them. That is the entire definition, and its poverty is the point: nothing in it mentions distance, position, or what the vertices represent.

Definition: Edges are undirected when the relation is symmetric (friendship, adjacency) and directed when it is not (following, dependency, one-way streets). They are weighted when each carries a number: distance, capacity, cost, probability.

Because the definition assumes so little, a theorem about graphs applies to every domain that fits the shape. "Find the cheapest route" and "find the least-error decoding of a message" and "find the most likely sequence of hidden states" are the same shortest-path problem, and one algorithm solves all three.

Full lesson text

All 10 steps on one page, for reading, reference, and search.

Show

1. Two sets and a relation

A graph G=(V,E)G = (V, E) is a set of vertices and a set of edges joining pairs of them. That is the entire definition, and its poverty is the point: nothing in it mentions distance, position, or what the vertices represent.

Definition: Edges are undirected when the relation is symmetric (friendship, adjacency) and directed when it is not (following, dependency, one-way streets). They are weighted when each carries a number: distance, capacity, cost, probability.

Because the definition assumes so little, a theorem about graphs applies to every domain that fits the shape. "Find the cheapest route" and "find the least-error decoding of a message" and "find the most likely sequence of hidden states" are the same shortest-path problem, and one algorithm solves all three.

2. Degree, and a theorem you can prove in one line

The degree of a vertex is how many edges meet it. Summing degrees over all vertices counts every edge exactly twice, once from each end:

vVdeg(v)=2E\sum_{v \in V} \deg(v) = 2|E|

That is the handshake lemma, and a corollary follows immediately: since the total is even, the number of odd-degree vertices must be even. You cannot build a graph with exactly three odd-degree vertices, however hard you try.

Key idea: This is what a graph-theoretic argument looks like. No algorithm ran, no case was checked, and the conclusion holds for every graph that will ever exist. Counting one quantity two different ways is the most productive single technique in combinatorics, and it settles the Konigsberg question later in this lesson.

3. Dense and sparse are different worlds

A graph on nn vertices has at most (n2)\binom{n}{2} edges, and that ceiling grows quadratically.

Maximum edges in a simple graph on n vertices
edges01k2k3k4k5kn=5n=10n=20n=50n=100
Source: Computed: n(n-1)/2

Real graphs land nowhere near that ceiling. A social network with a billion users averages a few hundred friends each, so E|E| is a small multiple of V|V|, not V2|V|^2. This is not a detail: it decides how you store the thing.

Adjacency matrixAdjacency list
Space$V
"Is there an edge u-v?"constant timeproportional to degree
Iterate neighbours of vv$V
Right fordense graphssparse graphs, which is nearly all of them

A million-vertex matrix is 101210^{12} entries. The same graph at average degree 10 is about 10710^7 list entries, a factor of 100,000.

4. Trees: the sparsest connected thing

A tree is a connected graph with no cycles, and it is rigid in a way that makes it easy to reason about. Three properties characterise it, and any two imply the third:

  • connected
  • acyclic
  • exactly V1|V| - 1 edges

Remove any edge and it disconnects; add any edge and it creates exactly one cycle. There is exactly one path between any two vertices, which is why file systems, org charts, parse trees and B-trees all take this shape when you want lookup without ambiguity.

Try it: Count the edges in any tree you can see, a directory listing, a family tree, a JSON document. It will be one fewer than the nodes, every time. If it is not, the structure has a cycle in it and is not a tree, which for a filesystem means a symlink loop and for a JSON document means it was not really JSON.

5. Directed and acyclic: the shape of dependencies

A directed acyclic graph has directed edges and no way to follow them back to where you started. That single restriction is what makes build systems, spreadsheets, task schedulers and version-control histories tractable: it guarantees a linear order consistent with every edge, called a topological order. Here ast.h must be processed before the three objects that include it, and all three before the link step, but their order among themselves is free.

flowchart LR
  E["ast.h"] --> A["parser.o"]
  E --> B["lexer.o"]
  E --> C["codegen.o"]
  A --> D["compiler"]
  B --> D
  C --> D

6. What a failed topological sort is telling you

Predict first

A build system runs a topological sort over its dependency graph and reports that no valid order exists. What has it actually discovered?

That if-and-only-if is what makes the technique useful. The algorithm does not merely fail to find an order, it certifies that none exists, and hands you the offending vertices as a by-product.

In practice: When a tool says "circular dependency detected", it usually already knows which nodes are involved, because they are precisely the ones left over when the sort stalls. Ask it to print them.

7. Bipartite graphs, and a test for them

A graph is bipartite when its vertices split into two sides with every edge crossing between them. Users and items, jobs and machines, students and courses, applicants and posts: the structure shows up wherever two kinds of thing relate to each other but not among themselves.

It has a clean characterisation. A graph is bipartite if and only if it contains no cycle of odd length. The reason is a two-colouring argument: walk the graph alternating colours, and you succeed unless some cycle forces a vertex to be both.

from collections import deque

def bipartite(adj, start):
    side = {start: 0}
    q = deque([start])
    while q:
        u = q.popleft()
        for v in adj[u]:
            if v not in side:
                side[v] = 1 - side[u]
                q.append(v)
            elif side[v] == side[u]:
                return False        # an odd cycle closed here
    return True

Matching problems on bipartite graphs are solvable in polynomial time, while the same questions on general graphs get much harder, which is why identifying the structure is worth the check.

8. Colouring: one problem wearing many hats

Assign a colour to each vertex so no edge joins two of the same colour. The minimum number needed is the chromatic number, and a startling range of scheduling problems is exactly this question.

  • Register allocation. Vertices are variables, edges join variables live at the same time, colours are CPU registers. A valid colouring is a valid assignment; running out of colours is a spill to memory.
  • Exam timetabling. Vertices are exams, edges join exams sharing a student, colours are time slots.
  • Frequency assignment. Vertices are transmitters, edges join those close enough to interfere, colours are channels.

Deciding whether three colours suffice is NP-complete in general, so compilers use fast heuristics rather than optimal colourings, and accept the occasional unnecessary spill.

Planar graphs, those drawable without crossings, are the famous exception: four colours always suffice. Appel and Haken proved it in 1976 by reducing the problem to 1,936 configurations and checking them by computer, the first major theorem to be settled that way, and a proof no human has ever read in full.

9. Where graph theory started, and where it stops

Konigsberg had seven bridges over the Pregel, and its residents wanted a walk crossing each exactly once. Euler answered it in 1736 by throwing away the map: only the connection pattern mattered.

His criterion is a counting argument. Any vertex you pass through uses two edges, one in and one out, so all interior vertices need even degree; only the start and end may be odd. Konigsberg's four landmasses had degrees 3, 3, 3 and 5, all odd, so no such walk exists. The proof took a paragraph and founded a field.

QuestionCriterionCost to decide
Euler path: use every edge once0 or 2 odd-degree verticeslinear in the graph size
Hamiltonian path: visit every vertex oncenone knownNP-complete

Key idea: Those two questions sound like variations on each other, and one is a degree check while the other is among the hardest problems we know. Nothing in the phrasing warns you which is which. Recognising the structure of a problem, rather than its wording, is what this lesson is for.

10. Modelling something as a graph

The hard part is rarely the algorithm. It is deciding what the vertices are, and a bad choice makes an easy problem look impossible.

  1. What is a vertex? Often not the obvious noun. For routing with time-dependent traffic, a vertex is a place and a time, not a place.
  2. What is an edge, and is it directed? Ask whether the relation is symmetric. Getting this wrong silently doubles or halves your answer.
  3. Does an edge carry a number? Weight turns "is it reachable" into "what does it cost", a different class of algorithm.
  4. Which special family is it in? Tree, DAG, bipartite and planar each unlock methods unavailable in general, so it pays to check before reaching for a general-purpose solver.
  5. Is it sparse? It almost certainly is, which decides the representation and often the practical running time more than the algorithm does.

The rest is looking up which algorithm applies, and the structure you identified in step 4 is what tells you which one that is.

Check your understanding

The lesson ends with a 5-question quiz. Take it in the player above to see your score.

  1. Can a graph have exactly three vertices of odd degree?
    • Yes, if it is disconnected
    • Yes, if it is directed
    • No: the degrees sum to twice the edge count, so the number of odd-degree vertices is even
    • Only if it contains a cycle
  2. A graph has 1,000,000 vertices and an average degree of 10. Which representation is appropriate?
    • Adjacency list: about 10^7 entries, versus 10^12 for a matrix
    • Adjacency matrix, for constant-time edge queries
    • Either, since both use space proportional to the edge count
    • A matrix, because the graph is too large for pointer-based structures
  3. Your build tool reports that a topological sort of the dependency graph is impossible. What does that prove?
    • The graph is disconnected
    • The graph contains a directed cycle
    • The graph is too large for the algorithm
    • Some dependency is missing from the graph
  4. Register allocation in a compiler is which graph problem?
    • Finding a Hamiltonian path through the variables
    • Topologically sorting the variables by first use
    • Finding a maximum matching between variables and registers
    • Colouring an interference graph, where colours are registers
  5. Why is deciding whether an Euler path exists easy while deciding a Hamiltonian path is NP-complete?
    • Euler paths only exist in planar graphs, which are a restricted family
    • Hamiltonian paths require weighted edges, which adds complexity
    • Euler paths have a local criterion, the parity of vertex degrees, while no comparable criterion is known for Hamiltonian paths
    • Euler paths are about edges, which are always fewer than vertices

Related lessons

Math
intermediate

Modular Arithmetic: Doing Maths on a Clock

Wrap the number line into a circle and addition and multiplication survive intact while division mostly does not. This lesson builds congruences, shows why you can reduce early to avoid overflow, works through Euclid's algorithm and modular inverses, and explains how a million-digit exponent becomes twenty multiplications.

10 steps·~15 min
Math
intermediate

Proof and Induction: Covering Infinitely Many Cases

Testing checks the cases you thought of; a proof covers all of them at once, including the ones nobody will ever run. This lesson builds direct proof, contradiction and induction as working tools, shows the two ways induction fails, and connects it to the loop invariants that make a program correct rather than merely untested.

10 steps·~15 min
Math
intermediate

Counting Without Listing

Combinatorics answers how many arrangements exist without producing any of them, which is what makes password strength, hash collisions and search-space size computable at all. This lesson builds the product rule, permutations, combinations, inclusion-exclusion and the pigeonhole principle, then applies them to problems where intuition is reliably wrong.

10 steps·~15 min
AI
advanced

Removing the Server: Gossip and Decentralized SGD

What happens when nobody coordinates: averaging by talking only to neighbours, why the graph's spectral gap sets the convergence rate, and how compressing messages by orders of magnitude still converges.

7 steps·~11 min