Graph Theory for Competitive Programmers: When to Use Which Algorithm
Competitive ProgrammingJan 2026 · 9 min read

GRAPH THEORY FOR COMPETITIVE PROGRAMMERS: WHEN TO USE WHICH ALGORITHM

BFS, Dijkstra, Bellman-Ford, Floyd-Warshall, A*. Every graph algorithm wins in specific domains and silently fails in others. Here is the decision framework I use in contests.

Graph problems are everywhere in competitive programming — and the biggest mistake beginners make is not implementing algorithms wrong, it is choosing the wrong algorithm. Each has a specific domain where it is optimal and edge cases where it silently fails.

BFS — Unweighted Shortest Path

BFS is the correct choice when all edge weights are equal (or effectively 1). It is O(V + E) and guarantees the shortest path in number of edges. Use it for: grid problems with uniform movement cost, word ladders, level-order traversal, any minimum-steps problem. Common mistake: using BFS on a weighted graph. It finds minimum-hop paths, not minimum-cost paths.

Dijkstra — Non-Negative Weighted Shortest Path

Dijkstra is the standard for weighted shortest path when all edge weights are >= 0. With a binary heap it is O((V + E) log V). Critical constraint: Dijkstra is incorrect with negative edges. If a problem has negative weights, it is probably not Dijkstra.

import heapq
def dijkstra(graph, start):
    dist = {start: 0}
    pq = [(0, start)]
    while pq:
        d, u = heapq.heappop(pq)
        if d > dist.get(u, float('inf')): continue
        for v, w in graph[u]:
            nd = dist[u] + w
            if nd < dist.get(v, float('inf')):
                dist[v] = nd
                heapq.heappush(pq, (nd, v))
    return dist

Bellman-Ford — Negative Weights and Cycle Detection

Bellman-Ford handles negative edge weights and can detect negative cycles. It is O(V*E) — much slower. Use it when: the problem has negative weights, you need to detect negative cycles (currency arbitrage, etc.), or edges have constraints making Dijkstra incorrect. Run V-1 iterations to find shortest paths; if distances still update on the Vth iteration, there is a negative cycle.

Floyd-Warshall — All Pairs Shortest Path

Floyd-Warshall computes shortest paths between all pairs of vertices in O(V^3). Use it when V is small (typically under 400), you need all-pairs distances, or the problem asks about reachability between all pairs. DP recurrence: dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]) for each intermediate vertex k.

A* — Heuristic-Guided Single-Target Search

A* is Dijkstra with an admissible heuristic h(n) estimating cost from n to the goal. If h never overestimates, A* is optimal and typically much faster than Dijkstra for single-target queries. In my A*/Dijkstra paper, A* reduced node exploration by 78.13% on the Lucknow road network because geographic distance (Haversine) is an excellent admissible heuristic for road graphs.

The Decision Tree

Unweighted graph → BFS. Weighted, non-negative, single source → Dijkstra. Negative weights or cycle detection → Bellman-Ford. All pairs, small V → Floyd-Warshall. Single target, geometric graph → A*.

Subtleties That Cost Points

Integer overflow: edge weights summing above 2^31 require long long. Not initialising distances to infinity properly. Using BFS on a weighted graph and getting wrong answers on test cases with unequal weights. Forgetting Dijkstra is wrong on negative weights — if you get WA on what looks like a Dijkstra problem, check for hidden negative weights. I am preparing for IOI where graph problems are a core component. The implementation details matter as much as knowing which algorithm to choose.