Graph Algorithms

60 min12 pages

What is Graph Algorithms?

Algorithms for traversing and analyzing graph structures like shortest path and spanning trees.

~60 min12 pages
graphsalgorithmsnetworks

Which graph representation is generally most memory-efficient for sparse graphs?

Adjacency matrix
Edge list
Adjacency list
Incidence matrix

Sign up to unlock quizzes

In a graph, a path is a sequence of _____ where consecutive vertices are connected by an edge.

Type your answer...

Sign up to unlock quizzes

Example: Basic Graph Traversal Setup

python
from collections import defaultdict, deque

# Create a simple undirected graph as an adjacency list
graph = defaultdict(list)
graph['A'] = ['B', 'C']
graph['B'] = ['A', 'D']
graph['C'] = ['A', 'D', 'E']
graph['D'] = ['B', 'C']
graph['E'] = ['C']

# The structure above supports BFS/DFS traversals to explore reachable nodes.

Example: Graph Representations

Consider a small network of five cities A, B, C, D, E with weighted roads:\nA - B (4), A - C (2), B - C (1), B - D (5), C - D (8), C - E (10), D - E (2)\n\nRepresentation choices:\n- Adjacency List: For each city, list its neighbors with edge weights.\n- Adjacency Matrix: A 5x5 matrix where entry [i][j] stores the weight or infinity if no direct road exists.\n- Edge List: A collection of (u, v, w) tuples.\n\nThese representations affect the efficiency of graph algorithms. For sparse graphs, adjacency lists are typically preferred; for dense graphs, adjacency matrices can simplify certain computations. Traversal algorithms rely on a way to quickly enumerate neighbors, which makes the choice of structure foundational to performance.

What is a fundamental difference between BFS and DFS in graph traversal?

BFS uses a stack, DFS uses a queue
BFS explores neighbors level by level using a queue, while DFS explores as far as possible along a branch using a stack (or recursion)
BFS only works on weighted graphs, DFS only on unweighted graphs
BFS finds the deepest node first, DFS finds the shallowest node first

Sign up to unlock quizzes

Graph traversal forms the backbone of many graph algorithms. Breadth-First Search (BFS) systematically visits nodes in increasing distance from the source, which makes it ideal for finding shortest paths in unweighted graphs and for level-by-level exploration. Depth-First Search (DFS) dives deep into one branch before backtracking, revealing the structure of connected components, detecting cycles, and enabling algorithms that rely on post-order processing. When implementing these traversals, you typically maintain a visited set to avoid reprocessing nodes and a data structure to hold the frontier: a queue for BFS or a stack/recursion for DFS. In weighted graphs, additional data structures like priority queues are used to select the next node to process based on accumulated weights. The choice between BFS and DFS depends on the problem: BFS for shortest path in unweighted graphs and graph reachability with minimal steps, DFS for cycle detection, topological ordering in DAGs, and graph decomposition.

For BFS, the typical data structure used to process the next node is a _____, ensuring level-by-level exploration.

Type your answer...

Sign up to unlock quizzes

Example: BFS on a Small Graph

python
def bfs(graph, start):
    visited = set([start])
    queue = [start]
    order = []
    while queue:
        v = queue.pop(0)
        order.append(v)
        for nei in graph[v]:
            if nei not in visited:
                visited.add(nei)
                queue.append(nei)
    return order

# Example graph:
# A: B, C; B: A, D; C: A, D, E; D: B, C; E: C
print(bfs({'A':['B','C'], 'B':['A','D'], 'C':['A','D','E'], 'D':['B','C'], 'E':['C']}, 'A'))  # ['A', 'B', 'C', 'D', 'E']

Which graph property is most directly exposed by a DFS traversal?

Shortest path in weighted graphs
Cycle detection and topological ordering in DAGs
Maximum flow in networks
Minimum spanning tree

Sign up to unlock quizzes

Which statement is true about traversal order in BFS on an unweighted graph?

It always finds the absolute shortest path to every node
It visits nodes in order of decreasing distance from the start
It visits nodes in order of nondecreasing distance from the start
It cannot determine distances without edge weights

Sign up to unlock quizzes

Shortest path problems are central in graph algorithms. In unweighted graphs, BFS naturally yields the shortest path in terms of the number of edges from a source to all reachable nodes. In weighted graphs, Dijkstra's algorithm computes the minimum total weight path by greedily selecting the next closest vertex using a priority queue. The core idea is to maintain a distance estimate for each node and to relax edges, updating the best-known distance when a shorter path is found. A practical insight is to use a min-heap (priority queue) to retrieve the next vertex with the smallest tentative distance efficiently. For graphs with negative weights, Bellman-Ford can handle them but may be slower; when all weights are non-negative, Dijkstra with a priority queue is typically preferred. If you need all-pairs shortest paths, algorithms like Floyd-Warshall or repeated Dijkstra are employed. Mastery here involves understanding the relaxation step, edge relaxation conditions, and when to stop the algorithm.

In Dijkstra's algorithm, a key operation is 'relaxation', which updates the _____ estimate of a vertex if a shorter path is found.

Type your answer...

Sign up to unlock quizzes

Example: Dijkstra's Pseudocode

python
function Dijkstra(graph, source):
    for each vertex v in graph: dist[v] = INFINITY; dist[source] = 0;
    Q = all vertices in graph initialized by dist[];
    while Q is not empty:
        u = vertex in Q with min dist[u]
        remove u from Q;
        for each neighbor v of u:
            alt = dist[u] + weight(u, v)
            if alt < dist[v]:
                dist[v] = alt
                previous[v] = u
    return dist

Which data structure provides the most efficient extraction of the next vertex with the smallest tentative distance in Dijkstra's algorithm?

Stack
Queue
Min-heap (priority queue)
Hash set

Sign up to unlock quizzes

Why can't Dijkstra's algorithm handle graphs with negative-weight edges without modification?

Negative weights cause the total distance to never update
Relaxation may lead to decreasing distances after a vertex has been removed from the priority queue, breaking correctness
Negative weights make the graph disconnected
The algorithm becomes non-deterministic

Sign up to unlock quizzes

Spanning trees are subgraphs that connect all vertices with the minimum number of edges. They preserve connectivity without cycles. Two classical algorithms produce spanning trees efficiently: Kruskal's algorithm builds the minimum spanning tree (MST) by repeatedly adding the smallest edge that does not create a cycle, typically using a disjoint-set (union-find) data structure to detect cycles. Prim's algorithm grows a tree from an arbitrary starting vertex by always attaching the smallest edge that connects the tree to a new vertex. Both algorithms assume a connected, undirected, weighted graph and aim to minimize total edge weight. The concept of MST is central in network design, where you want to connect points with the least total wiring or cost while maintaining full reachability. In practice, MSTs underpin clustering, image segmentation, and heuristic approximations for more complex network problems.

Kruskal's algorithm uses a _____ data structure to quickly detect cycles while adding the smallest edges.

Type your answer...

Sign up to unlock quizzes

Example: Prim's MST Idea

python
graph = {
    'A': {'B': 4, 'H': 8},
    'B': {'A': 4, 'C': 8, 'H': 11},
    'C': {'B': 8, 'D': 7, 'F': 4, 'G': 2},
    'D': {'C': 7, 'E': 9},
    'E': {'D': 9, 'F': 14},
    'F': {'E': 14, 'G': 4},
    'G': {'F': 4, 'H': 2, 'C': 2},
    'H': {'A': 8, 'B': 11, 'G': 2}
}
# Prim's algorithm would start at a node and repeatedly attach the smallest edge crossing the growing tree.

What is the primary goal of a Minimum Spanning Tree problem?

Maximize the number of edges in the tree
Minimize the total weight of the edges in the tree
Find the longest path in the graph
Identify all cycles in the graph

Sign up to unlock quizzes

Which algorithm grows a single tree by attaching the smallest edge that connects to a new vertex?

Kruskal's algorithm
Prim's algorithm
Dijkstra's algorithm
Bellman-Ford algorithm

Sign up to unlock quizzes

Network flow theory studies the maximum amount of a commodity that can be transferred from a source to a sink through a network with capacity constraints. The classic problem is the max-flow, min-cut theorem: the maximum flow equals the minimum cut capacity separating source and sink. Algorithms like Ford-Fulkerson, Edmonds-Karp (which uses BFS for augmenting paths), and Dinic's algorithm solve this by repeatedly finding augmenting paths and augmenting flow along them. Graphs with capacities allow you to model real-world systems: traffic, data routing, supply chains. A residual graph tracks remaining capacity and guides the next augmentation. Understanding flows requires grasping the notions of capacity, residual capacity, augmenting paths, and cuts. In practice, you model the network, initialize zero flow, and iteratively push flow until no more augmenting paths exist, achieving a maximum flow that cannot be improved without increasing capacity.

What fundamental theorem connects maximum flow to a minimum cut in a network?

Pigeonhole principle
Max-flow min-cut theorem
Kruskal's theorem
Euler's theorem

Sign up to unlock quizzes

Example: Edmonds-Karp Augmenting Path

python
def bfs(residual, source, sink):
    parent = {source: None}
    q = deque([source])
    while q:
        u = q.popleft()
        for v, cap in residual[u].items():
            if cap > 0 and v not in parent:
                parent[v] = u
                if v == sink:
                    path = []
                    cur = sink
                    while cur != source:
                        path.append((parent[cur], cur))
                        cur = parent[cur]
                    path.reverse()
                    return path
                    
                q.append(v)
    return None

# This finds an augmenting path; you would then push flow along it and update residuals.

In the context of max-flow, what is a residual graph?

A graph with current capacities minus the flow
A graph with all edges removed
A subgraph containing only source edges
A graph that ignores edge directions

Sign up to unlock quizzes

An augmenting path increases total flow by the _____ possible amount along that path.

Type your answer...

Sign up to unlock quizzes

Planar graphs and graph drawing are practical topics where structure matters. Planarity concerns whether a graph can be drawn on a plane without crossing edges. Some algorithms assume planarity to simplify computations. Graph drawing aims to place vertices and route edges aesthetically and legibly, which improves understanding and visualization in domains like circuit design or social networks. While many graph algorithms focus on combinatorial properties, visual representations can reveal patterns such as communities, clusters, and central nodes. Techniques like BFS layering, radial layouts, and force-directed methods combine algorithmic insights with geometric reasoning to produce informative diagrams. Understanding planarity also links to powerful theorems such as Kuratowski's theorem, which characterizes non-planar graphs via minor containment. In practice, when you model problems, choosing representations that support efficient traversal, matching, or flow computations is as important as the theoretical correctness of the algorithm.

Which statement best describes a planar graph?

A graph with no cycles
A graph that can be drawn on a plane without edge crossings
A graph where all edges have equal weight
A graph with only directed edges

Sign up to unlock quizzes

Example: Kuratowski's Theorem (Intuition)

Kuratowski's theorem states that a finite graph is planar if and only if it does not contain a subdivision of K5 (complete graph on 5 vertices) or K3,3 (utility graph) as a subgraph. This gives a structural criterion for planarity, guiding both theoretical reasoning and practical drawing constraints. In practice, when solving layout problems, you may avoid creating subgraphs known to induce non-planarity or use embeddings that respect planarity to simplify rendering and algorithmic steps that rely on planar properties.

What is a common goal of force-directed layout algorithms in graph drawing?

Minimize edge crossings and evenly space nodes
Maximize the distance between all pairs of nodes
Ensure all edges have equal length
Arrange nodes in numerical order

Sign up to unlock quizzes

A graph is planar if it can be drawn on a plane with _____ edges crossing.

Type your answer...

Sign up to unlock quizzes

You've previewed 6 of 12 pages

Sign up free to unlock the rest of this lesson and start tracking your progress.

6 more pages waiting:

  • Page 7
  • Page 8
  • Page 9
  • Page 10
  • +2 more...

Related Topics