Back to Graph Theory Series

Part 2: Combinatorics, Probability & Algorithm Complexity

August 30, 2026 Wasil Zafar 26 min read

Counting dictates how many graphs and network paths can exist. Probability explains how random networks form and self-organize. Asymptotic analysis (Big-O) enables us to evaluate and optimize graph algorithms before writing a single line of code.

Table of Contents

  1. 1. Combinatorics: The Art of Counting
  2. 2. Probability & Random Graphs
  3. 3. Algorithm Correctness & Invariants
  4. 4. Asymptotic Analysis & Big-O Notation
  5. 5. Underlying Data Structures & Complexity Classes
  6. 6. Hands-On Exercises & Solutions
  7. 7. Conclusion & Next Steps

1. Combinatorics: The Art of Counting

Before building social networks, routing internet packets, or solving graph coloring problems, we must answer fundamental counting questions: How many edges can a graph with \(n\) vertices have? How many unique networks can we construct? How many possible routes connect two nodes? Combinatorics provides the exact mathematical framework to answer these questions.

Permutations, Combinations & Graph Search Spaces

A permutation counts ordered arrangements of elements. A combination counts unordered selections where sequence does not matter.

$$P(n, k) = \frac{n!}{(n-k)!} \qquad \binom{n}{k} = \frac{n!}{k!(n-k)!}$$

Real-World Analogy: Imagine a telecommunication network connecting \(n\) server data centers.
• Choosing a one-way directional pipe from server \(A\) to server \(B\) depends on order \((A \to B \neq B \to A)\). This is a permutation.
• Constructing a two-way fiber optic link between server \(A\) and server \(B\) does not depend on order \(\{A, B\}\). This is a combination.

In an undirected simple graph with \(n\) vertices, any two distinct vertices can share at most one edge. Therefore, the total number of possible candidate edges is given by the binomial coefficient \(\binom{n}{2}\):

$$\binom{n}{2} = \frac{n(n-1)}{2}$$

Combinatorial Explosion in Network Topologies

Since each of the \(\binom{n}{2}\) possible edges can either exist or not exist (2 choices per pair), the total number of distinct labeled simple graphs that can be built on \(n\) vertices is:

$$2^{\binom{n}{2}}$$

For a tiny network of just 5 nodes, there are \(2^{10} = 1,024\) possible graph structures. For a network of 10 nodes, there are \(2^{45} \approx 35.18 \text{ trillion}\) unique configurations!

The Pigeonhole Principle & The Party Problem

The Pigeonhole Principle states: If \(k+1\) or more items are put into \(k\) boxes, then at least one box must contain two or more items. While deceptively simple, it is one of the most powerful tools in graph theory.

Theorem Proof

Every Graph Contains at Least Two Vertices with Equal Degrees

Claim: In any simple graph with \(n \ge 2\) vertices, there exist at least two vertices that have the exact same degree.

Proof: Let \(G = (V, E)\) be a simple graph with \(n\) vertices. The degree of any vertex \(\deg(v)\) represents the number of neighbors it connects to. Thus, \(\deg(v)\) must be an integer between \(0\) and \(n-1\). That gives \(n\) possible degree values (our "boxes") for \(n\) vertices (our "pigeons").

However, degree \(0\) (a completely isolated vertex) and degree \(n-1\) (a vertex connected to every other node) cannot coexist in the same simple graph! If a vertex has degree \(n-1\), it connects to all other vertices, meaning no vertex can be isolated (degree 0).

Therefore, the available degree values in any graph of size \(n\) can span at most \(n-1\) distinct choices. By placing \(n\) vertices into \(n-1\) degree choices, the Pigeonhole Principle guarantees that at least two vertices must share the exact same degree value. \(\blacksquare\)

Pigeonhole Degree Sequences

Double Counting & The Handshaking Lemma

Double counting is a proof technique where we calculate the size of a set in two different ways to establish an algebraic identity.

Consider calculating the total number of endpoint connections in a graph. We can sum up the degrees of every vertex \(\sum_{v \in V} \deg(v)\). Alternatively, notice that every single edge \(e = (u, v)\) has exactly two endpoints, so it contributes exactly \(2\) to the total degree count. Equating these two counts gives the fundamental Handshaking Lemma:

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

2. Probability & Random Graphs

Historical Context: Erdős, Rényi & The Random Graph Model

In 1959, Hungarian mathematicians Paul Erdős and Alfréd Rényi revolutionized graph theory by introducing randomness into graph construction. Instead of analyzing specific deterministic graphs, they asked: What properties emerge on average when edges are created randomly?

Historical Foundation

The Erdős–Rényi Model: \(G(n, p)\)

In the \(G(n, p)\) model, we begin with \(n\) isolated vertices. For every possible pair among the \(\binom{n}{2}\) pairs, an edge is added independently with probability \(p\) (\(0 \le p \le 1\)).

This model helps computer scientists understand how phase transitions occur in real-world systems — such as how local internet router links spontaneously form a globally connected web when link probabilities cross a critical threshold.

Expected Values & The Probabilistic Method

A random variable \(X\) assigns a real number to each outcome in a probability space. The Expected Value \(E[X]\) represents the long-term average value of \(X\):

$$E[X] = \sum x \cdot P(X = x)$$

By Linearity of Expectation, the expected value of a sum of random variables is equal to the sum of their individual expectations, regardless of whether they are independent:

$$E[X_1 + X_2 + \dots + X_k] = E[X_1] + E[X_2] + \dots + E[X_k]$$

Worked Calculation: Expected Edge Count in $G(n, p)$

Let $X$ be the total number of edges in a random graph $G(n, p)$. For each possible edge pair $i \in \{1, 2, \dots, \binom{n}{2}\}$, define an indicator random variable $X_i$ where $X_i = 1$ if edge $i$ exists, and $X_i = 0$ otherwise.

The probability $P(X_i = 1) = p$, so $E[X_i] = 1 \cdot p + 0 \cdot (1-p) = p$. Total edges $X = \sum_{i=1}^{\binom{n}{2}} X_i$. Applying Linearity of Expectation:

$$E[X] = \sum_{i=1}^{\binom{n}{2}} E[X_i] = \binom{n}{2} p = \frac{n(n-1)p}{2}$$

If a network has $n = 100$ servers and each connection forms with probability $p = 0.05$, the expected total number of active connections is $\frac{100 \times 99}{2} \times 0.05 = 247.5$ edges.

3. Algorithm Correctness & Invariants

Preconditions, Postconditions & Loop Invariants

A graph algorithm is not merely a set of execution steps; it is a mathematical function that must be proven correct. We establish algorithm validity using three constructs:

  • Precondition: The mandatory state of the input data before execution (e.g., "The graph must be connected and non-empty").
  • Postcondition: The guaranteed state of the output upon completion (e.g., "Returns the shortest path distance between source $s$ and target $t$").
  • Loop Invariant: A logical property that remains true before, during, and after every iteration of a loop.

To prove correctness via a loop invariant, we apply mathematical induction across loop iterations:
1. Initialization: The invariant holds prior to the first iteration.
2. Maintenance: If the invariant holds before iteration $k$, it remains true after iteration $k$.
3. Termination: When the loop terminates, the invariant provides a assertion proving the algorithm postcondition.

Below is Python code demonstrating how loop invariants verify the Handshaking Lemma programmatically:

def verify_handshaking_lemma(adj_list):
    """
    Precondition: adj_list is a valid dictionary representing an undirected graph.
                  Keys are vertex IDs, values are lists of neighbor IDs.
    Postcondition: Returns True if sum(degrees) == 2 * total_edges, preserving invariant.
    """
    degree_sum = 0
    seen_edges = set()
    
    # Loop Invariant: After checking 'k' vertices, degree_sum equals 
    # the sum of degrees of those 'k' processed vertices.
    for u, neighbors in adj_list.items():
        degree_sum += len(neighbors)
        for v in neighbors:
            # Store undirected edge as an ordered tuple (min, max) to avoid duplicate counting
            edge = (min(u, v), max(u, v))
            seen_edges.add(edge)
            
    total_edges = len(seen_edges)
    
    # Termination check: Postcondition verification
    assert degree_sum == 2 * total_edges, "Handshaking Lemma violated!"
    return degree_sum, total_edges

# Test on a 4-node cycle graph (A-B-C-D-A)
cycle_graph = {
    'A': ['B', 'D'],
    'B': ['A', 'C'],
    'C': ['B', 'D'],
    'D': ['C', 'A']
}

deg_sum, num_edges = verify_handshaking_lemma(cycle_graph)
print(f"Degree Sum: {deg_sum} | Total Edges: {num_edges} | Formula 2*|E|: {2 * num_edges}")

4. Asymptotic Analysis & Big-O Notation

Big-O, Big-Omega (\(\Omega\)) & Big-Theta (\(\Theta\))

When running algorithms on massive real-world graphs (like mapping billions of web pages), exact step counts become impractical. We use Asymptotic Notation to classify how running time or memory usage scales as input size approaches infinity.

NotationMathematical MeaningIntuitive BoundaryGraph Algorithm Example
Big-O (\(O\))\(f(n) \le c \cdot g(n)\) for all \(n \ge n_0\)Upper bound (Worst case)Breadth-First Search: \(O(|V| + |E|)\)
Big-Omega (\(\Omega\))\(f(n) \ge c \cdot g(n)\) for all \(n \ge n_0\)Lower bound (Best case)Comparison-based Graph Sorting: \(\Omega(n \log n)\)
Big-Theta (\(\Theta\))\(c_1 g(n) \le f(n) \le c_2 g(g(n))\)Tight bound (Exact rate)Adjacency Matrix Edge Search: \(\Theta(1)\)
Complexity Growth Rates (Slowest to Fastest)
flowchart LR
    A["O(1) Constant"] --> B["O(log V) Logarithmic"]
    B --> C["O(V + E) Linear"]
    C --> D["O(E log V) Near-Linear"]
    D --> E["O(V²) Quadratic"]
    E --> F["O(V³) Cubic"]
    F --> G["O(2ⱽ) Exponential"]
            

Recurrences & The Master Theorem

Divide-and-conquer algorithms break a graph problem of size \(n\) into \(a\) smaller subproblems, each of size \(n/b\), spending \(f(n)\) time recombining results. Their running times are expressed as recurrence relations:

$$T(n) = a T\left(\frac{n}{b}\right) + f(n)$$

The Master Theorem gives us an immediate asymptotic solution by comparing $f(n)$ to $n^{\log_b a}$:

The Master Theorem Rules

1. Subproblem Dominated: If $f(n) = O\left(n^{\log_b a - \epsilon}\right)$ for some $\epsilon > 0$, then $T(n) = \Theta\left(n^{\log_b a}\right)$.
2. Balanced Growth: If $f(n) = \Theta\left(n^{\log_b a}\right)$, then $T(n) = \Theta\left(n^{\log_b a} \log n\right)$.
3. Work Dominated: If $f(n) = \Omega\left(n^{\log_b a + \epsilon}\right)$ and satisfies regularity conditions, then $T(n) = \Theta(f(n))$.

5. Underlying Data Structures & Complexity Classes

An algorithm's asymptotic efficiency depends heavily on the data structures chosen to represent the graph:

Graph RepresentationSpace ComplexityCheck Edge \((u, v)\)List All Neighbors of \(u\)
Adjacency Matrix\(\Theta(|V|^2)\)\(O(1)\)\(\Theta(|V|)\)
Adjacency List\(\Theta(|V| + |E|)\)\(O(\deg(u))\)\(\Theta(\deg(u))\)
Edge List\(\Theta(|E|)\)\(\Theta(|E|)\)\(\Theta(|E|)\)

Finally, when analyzing problem difficulty, computer scientists divide problems into complexity classes:
• \(\mathbf{P}\): Problems solvable in polynomial time (e.g., Shortest Path \(O(|V|^2)\)).
• \(\mathbf{NP}\): Problems whose proposed solutions can be verified in polynomial time (e.g., Hamiltonian Cycle).
• \(\mathbf{NP}\text{-Complete}\): The hardest problems in \(\mathbf{NP}\). If an efficient polynomial-time algorithm exists for one, every problem in \(\mathbf{NP}\) can be solved in polynomial time.

6. Hands-On Exercises & Solutions

Practice Problems

Exercise 1 (Combinatorics): How many distinct simple graphs can be constructed on $n = 4$ labeled vertices? Calculate the exact value and list the possible edge count distribution.

Exercise 2 (Master Theorem): A divide-and-conquer graph partitioning algorithm breaks a graph into 4 equal subproblems of size $n/2$ and takes linear time $O(n)$ to merge the cuts. Write the recurrence $T(n)$ and solve for Big-Theta complexity.

Exercise 3 (Pigeonhole Principle Challenge): Prove that in any connected graph with $n \ge 6$ vertices, there exists either a clique (completely connected subgraph) of size 3 OR an independent set (set of mutually disconnected vertices) of size 3.

Click to View Solutions

Solution 1:
The maximum possible edges for $n = 4$ is $\binom{4}{2} = \frac{4 \times 3}{2} = 6$.
The total number of unique labeled graphs is $2^6 = 64$.
Edge distribution: 1 graph with 0 edges, 6 with 1 edge, 15 with 2 edges, 20 with 3 edges, 15 with 4 edges, 6 with 5 edges, and 1 with 6 edges (Total sum = 64).

Solution 2:
Recurrence relation: $T(n) = 4T(n/2) + O(n)$, so $a = 4, b = 2, f(n) = n$.
Compute critical exponent: $n^{\log_b a} = n^{\log_2 4} = n^2$.
Since $f(n) = O(n^{2 - \epsilon})$ for $\epsilon = 1$, Case 1 of the Master Theorem applies: $T(n) = \Theta(n^2)$.

Solution 3:
This is Ramsey's Theorem for $R(3, 3) = 6$. Pick any vertex $v$. It has 5 remaining edges to other nodes. By the Pigeonhole Principle, $v$ must have either $\ge 3$ neighbors connected to it (edges) OR $\ge 3$ non-neighbors (non-edges).
Case 1: If $v$ has 3 neighbors $\{a, b, c\}$, and if any pair among them is connected, they form a 3-clique with $v$. If none are connected, $\{a, b, c\}$ forms an independent set of size 3. $\blacksquare$

7. Conclusion & Next Steps

You now possess a complete discrete-math toolkit for analyzing graph problems: combinatorics for measuring graph space sizes, the pigeonhole principle and double-counting for proving invariants, expected values for random graph dynamics, and asymptotic Big-O bounds for evaluating algorithm runtime efficiency.

Next in the Series

In Part 3: Linear Algebra & Topology Primer for Graph Theory, we build the matrix and topology machinery — adjacency matrices, Laplacian spectra, and planarity — that powers spectral graph theory.