Graph Algorithms

A graph is a set of nodes (vertices) connected by edges — the most general way to model relationships. Roads between cities, friends in a social network, dependencies between tasks, links between web pages: all are graphs. Once you recognize a problem as a graph problem, a well-developed toolkit of algorithms applies, which is why graphs are one of the most important topics in computer science and interviews.

The two foundational traversals — breadth-first search (BFS) and depth-first search (DFS) — underlie most of the rest. Add shortest-path and ordering algorithms on top, and you can solve a remarkable range of real problems.

TL;DR

Quick Example

Graphs are usually stored as an adjacency list — each node maps to its neighbors:

Representations

Graphs can be directed (edges have direction) or undirected, and weighted (edges carry a cost) or unweighted.

Traversal: BFS & DFS

Both are O(V + E).

Shortest Paths & Ordering

What Graphs Model

Best Practices

Common Mistakes

Forgetting to track visited nodes

Using BFS for weighted shortest paths

FAQ

When should I use BFS vs DFS?

Use BFS when you need the shortest path in an unweighted graph or want to explore in order of distance from the start (fewest steps, nearest first) — it uses a queue and visits level by level. Use DFS when you need to explore deeply: detecting cycles, checking connectivity, finding paths, or topological sorting — it uses recursion or a stack. Both are O(V + E); the choice is about the order you want to visit nodes and what the problem asks.

What's the difference between an adjacency list and an adjacency matrix?

An adjacency list stores, for each node, a list of its neighbors — O(V + E) space, efficient for sparse graphs (the common case), but checking "is there an edge between A and B?" can take O(degree). An adjacency matrix is a V×V grid marking every possible edge — O(1) edge checks but O(V²) space regardless of how few edges exist. Use the list by default; use the matrix only for dense graphs or when constant-time edge queries dominate.

Why can't I use Dijkstra's algorithm with negative edge weights?

Dijkstra assumes that once it finalizes the shortest distance to a node, that distance can't improve — which holds only when all weights are non-negative (you can never reach a node more cheaply by taking a longer detour). A negative edge can make a longer path cheaper, breaking that assumption and producing wrong results. For graphs with negative weights, use Bellman-Ford, which is slower (O(V·E)) but handles them and can detect negative cycles.

What is topological sorting used for?

Topological sort orders the nodes of a directed acyclic graph (DAG) so that every edge goes from earlier to later — i.e., every prerequisite comes before what depends on it. It's the algorithm behind build systems (compile dependencies first), task schedulers, course prerequisite ordering, and package dependency resolution. If the graph has a cycle, no valid ordering exists — which is exactly how these systems detect circular dependencies.

Related Topics

References