By the end of this chapter you'll be able to…

  • 1State the common shape shared by every graph algorithm here
  • 2Explain how finalisation timing determines an algorithm's preconditions
  • 3State the cost of breadth-first and depth-first search
  • 4Find connected components and detect cycles by traversal
  • 5Produce a topological order by both DFS finishing times and Kahn's algorithm
  • 6Explain why Kahn's algorithm doubles as a cycle detector
  • 7State the cut and cycle properties and use them to justify MST edges
  • 8Compare Kruskal and Prim on structure, cost and graph density
  • 9Explain when an MST is unique
  • 10Explain why adding a constant preserves an MST but can change a shortest path
  • 11Describe union-find with union by rank and path compression
  • 12State why Kruskal's cost is dominated by the sort
  • 13Trace Dijkstra's algorithm and identify when a tentative distance is revised
  • 14Explain precisely why a negative edge breaks Dijkstra
  • 15Trace Bellman-Ford and detect a negative cycle with the V-th pass
  • 16Solve shortest paths on a DAG in linear time
  • 17State the Floyd-Warshall recurrence and why k must be the outer loop
  • 18Detect a negative cycle from the Floyd-Warshall diagonal
  • 19Describe Johnson's algorithm and when it beats Floyd-Warshall
  • 20Describe Kosaraju's algorithm and why the transpose is used
  • 21Explain why the condensation of a graph is always acyclic
  • 22Apply the selection procedure to choose an algorithm from stated conditions
💡
Why this chapter matters in GATE
Graph algorithms look like a long list of unrelated procedures with unrelated proofs, but they are variations on one shape: every algorithm visits vertices and edges and attaches bookkeeping to that visit. Breadth-first search records a discovery order, Dijkstra a tentative distance, Kruskal which components have merged, Floyd-Warshall which intermediates are permitted. What distinguishes them is what the bookkeeping records and, crucially, when it dares to declare something final. A greedy algorithm finalises early and needs a proof that doing so is safe; a dynamic program finalises late and pays for the caution in running time. That single distinction explains the whole structure of preconditions in this chapter: Dijkstra forbids negative edges because it finalises the closest vertex immediately, while Bellman-Ford tolerates them because it commits to nothing until the last pass.

Before you start — revise these

🔗
Binary Heaps & Graphs as Data Structures
Adjacency representations, traversal costs and the priority queue that makes Dijkstra and Prim efficient are all developed there.
🔗
Algorithm Design: Greedy, Divide & Conquer, Dynamic Programming
The greedy-versus-dynamic-programming distinction is exactly what separates Dijkstra from Bellman-Ford and Prim from Floyd-Warshall.
🔗
Discrete Mathematics
Graph terminology, connectivity, the edge threshold for a cycle and the tree edge count all come from there.

Graph Algorithms

Graph algorithms look like a long list of unrelated procedures with unrelated proofs. They are better seen as variations on one shape.

Every algorithm in this chapter visits vertices and edges, and attaches bookkeeping to that visit. Breadth-first search records a discovery order. Dijkstra records a tentative distance. Kruskal records which components have merged. Floyd-Warshall records which intermediate vertices have been permitted.

What distinguishes them is what the bookkeeping records and, crucially, when it dares to declare something final. A greedy algorithm finalises early and needs a proof that it is safe to do so; a dynamic program finalises late and pays for the caution in running time.

That single distinction explains the whole chapter's structure of preconditions. Dijkstra finalises a vertex the moment it is closest, so a negative edge could invalidate that decision and is forbidden. Bellman-Ford never finalises until the last pass, so it tolerates negative edges and costs more.

The second organising fact is that almost every cost here is or a small factor above it. A traversal is linear; adding a priority queue costs a logarithm; considering all pairs costs a factor of . Knowing which of those three a problem needs is most of the complexity question.

1. Traversal and Its Immediate Consequences

Breadth-first and depth-first search both cost with adjacency lists, and both visit every reachable vertex once.

Breadth-first search uses a queue and yields shortest paths in unweighted graphs, because it expands one distance layer at a time.

Depth-first search uses a stack and yields structural information: discovery and finishing times, and an edge classification into tree, back, forward and cross edges.

Three problems follow almost directly from a traversal.

Connected components are found by running a traversal from each unvisited vertex and counting the restarts.

Cycle detection in a directed graph is the presence of a back edge. In an undirected graph, it is any edge to a visited vertex other than the immediate parent.

Topological sorting of a directed acyclic graph has two standard formulations.

The depth-first version lists vertices in decreasing order of finishing time. The correctness argument is short: for any edge from to in an acyclic graph, must finish after , so precedes in the reversed order.

Kahn's algorithm is the iterative version: repeatedly remove a vertex of in-degree zero and decrement its neighbours' in-degrees. If vertices remain when no in-degree-zero vertex exists, the graph has a cycle, which makes it a cycle detector as well.

A topological order is not unique unless the graph has a Hamiltonian path, and counting the valid orders is a separate and harder problem.

2. Minimum Spanning Trees

A minimum spanning tree connects every vertex with the least total edge weight, using exactly edges.

Two properties justify every MST algorithm.

The cut property: for any partition of the vertices into two sets, the minimum-weight edge crossing the partition belongs to some minimum spanning tree.

The cycle property: for any cycle, the maximum-weight edge in that cycle belongs to no minimum spanning tree.

Kruskal's algorithm sorts all edges by weight and adds each one that does not create a cycle, using a union-find structure to test connectivity. Sorting dominates, giving , which is since .

Prim's algorithm grows a single tree from an arbitrary start, repeatedly adding its cheapest outgoing edge. With a binary heap it costs ; with a simple array it costs , which is better for dense graphs.

AlgorithmStructure usedCostSuits
KruskalUnion-findSparse graphs
Prim with heapPriority queueSparse graphs
Prim with arrayArray scanDense graphs

The minimum spanning tree is unique if all edge weights are distinct. With repeated weights several trees may tie, though the total weight is of course the same for all of them.

Adding a constant to every edge weight does not change the MST, since every spanning tree has exactly edges and all totals shift equally. Multiplying does not change it either, provided the constant is positive.

Kruskal's algorithm depends entirely on a union-find structure, which maintains disjoint sets under two operations: find the representative of an element's set, and union two sets.

The naive implementation is a forest of trees where each node points at its parent, and find walks to the root. Without optimisation a tree can degenerate into a chain and find costs .

Two optimisations fix this and are examined together.

Union by rank attaches the shorter tree under the taller one, which keeps the height logarithmic because a tree of height requires at least nodes.

Path compression flattens the path during a find, repointing every node visited directly at the root, so subsequent finds on those nodes are immediate.

With both, the amortised cost per operation is effectively constant — formally the inverse Ackermann function, which is at most 4 for any input that will ever be constructed. This is why Kruskal's cost is dominated by the sort rather than by the connectivity tests.

3. Single-Source Shortest Paths

Three algorithms address progressively harder cases.

Breadth-first search solves the unweighted case in .

Dijkstra's algorithm handles non-negative weights. It maintains tentative distances, repeatedly finalises the closest unfinalised vertex, and relaxes its outgoing edges. With a binary heap the cost is .

The non-negativity requirement is not a technicality. Finalising the closest vertex is safe only because no later path can arrive more cheaply, and that argument depends on every subsequent edge being non-negative.

Bellman-Ford handles negative weights. It relaxes every edge times, which suffices because any shortest path has at most edges, and costs .

A -th pass that still improves some distance proves a negative cycle exists, which is the standard detection method and something Dijkstra cannot do at all.

On a directed acyclic graph, shortest paths are computable in by relaxing edges in topological order — faster than Dijkstra and correct even with negative weights, since the acyclicity removes the difficulty.

4. All-Pairs Shortest Paths

Floyd-Warshall is a dynamic program over which vertices are permitted as intermediates.

The outermost loop must be over , the intermediate vertex, and putting it inside gives wrong answers. This is the single most examined implementation detail in the chapter.

The cost is with space, it handles negative edges, and a negative value on the diagonal after completion signals a negative cycle.

Running Dijkstra from every vertex costs , which beats Floyd-Warshall on sparse graphs but requires non-negative weights.

Johnson's algorithm removes that restriction by reweighting the graph with Bellman-Ford so that all weights become non-negative while preserving shortest paths, then running Dijkstra from each vertex. It costs and is the method of choice for sparse graphs with negative edges.

5. Why the Preconditions Exist

Each restriction traces back to what the algorithm finalises and when.

Dijkstra forbids negative edges because it declares a vertex final the moment it is closest. A negative edge discovered later could reduce that distance, and nothing would revisit it.

Bellman-Ford permits them because it finalises nothing until all passes complete, so a late improvement is still incorporated.

Neither handles a negative cycle meaningfully, because a path can circle it repeatedly and reduce its cost without bound, so no shortest path exists. Bellman-Ford's contribution is to detect this rather than to solve it.

Prim and Kruskal permit negative weights freely, because a spanning tree must contain exactly edges regardless of sign, so there is no incentive to circle anything.

Floyd-Warshall permits negative edges because it considers every intermediate vertex systematically rather than committing early.

6. Complexity Summary

ProblemAlgorithmCostCondition
TraversalBFS or DFSNone
Topological sortDFS or KahnAcyclic
Strongly connected componentsKosaraju or TarjanDirected
MSTKruskal or PrimUndirected connected
Unweighted shortest pathBFSNone
Shortest path, non-negativeDijkstraNo negative edges
Shortest path, negativeBellman-FordNo negative cycle
Shortest path on a DAGTopological relaxationAcyclic
All pairsFloyd-WarshallNo negative cycle

Kosaraju's algorithm finds strongly connected components with two depth-first searches: one on the graph to record finishing times, and one on the transpose in decreasing order of those times. Each tree in the second search is one component.

Why the transpose works is worth a sentence: reversing every edge leaves the strongly connected components unchanged, since mutual reachability is symmetric, but it prevents the second search from escaping a component into one that finishes later.

Contracting each strongly connected component to a single vertex yields the condensation, which is always a directed acyclic graph — because a cycle among components would merge them into one.

7. Choosing an Algorithm

The selection procedure is short and mechanical.

Ask first whether the graph is weighted. If not, breadth-first search answers shortest paths in linear time and nothing more elaborate is needed.

Then ask whether any weight is negative. If none is, Dijkstra applies. If some are, Bellman-Ford is required, and if the graph is additionally acyclic, topological relaxation is faster than both.

Then ask whether one source or all pairs is needed. All pairs on a dense graph favours Floyd-Warshall at ; all pairs on a sparse graph favours repeated Dijkstra, or Johnson's if negative edges are present.

8. Worked Examples

Example 1. A weighted undirected graph has edges AB=4, AC=3, BC=1, BD=2, CD=5, DE=6. Find a minimum spanning tree using Kruskal's algorithm.

Sort the edges by weight: BC=1, BD=2, AC=3, AB=4, CD=5, DE=6.

BC=1: A, B, C, D, E are all separate. Adding BC creates no cycle. Accept. Components: {B,C}, {A}, {D}, {E}.

BD=2: B and D are in different components. Accept. Components: {B,C,D}, {A}, {E}.

AC=3: A and C are in different components. Accept. Components: {A,B,C,D}, {E}.

AB=4: A and B are now in the same component, so this would create a cycle. Reject.

CD=5: C and D are in the same component. Reject.

DE=6: D and E are in different components. Accept. Components: {A,B,C,D,E}.

The tree is BC, BD, AC, DE with total weight , using exactly edges.

Note the cycle property at work. Edge AB was rejected as the heaviest edge on the cycle A-B-C-A, and CD as the heaviest on B-C-D-B. Both are exactly what the cycle property predicts.

Example 2. Run Dijkstra's algorithm from S on a directed graph with edges S→A=4, S→B=1, B→A=2, A→C=5, B→C=8.

Initialise: distance to S is 0, all others infinite.

Finalise S (distance 0). Relax its edges: A becomes 4, B becomes 1.

The closest unfinalised vertex is B at 1. Finalise it. Relax B's edges: A via B is , which improves on 4, so A becomes 3. C via B is , so C becomes 9.

The closest unfinalised is A at 3. Finalise it. Relax A's edge: C via A is , which improves on 9, so C becomes 8.

Finalise C at 8.

Final distances: S=0, B=1, A=3, C=8.

The instructive step is A being improved from 4 to 3 after B was finalised. Dijkstra's guarantee is only that a finalised distance is correct; tentative distances are revised freely until the vertex is chosen.

Example 3. Why does Dijkstra fail on this graph: S→A=2, S→B=5, B→A=−4?

Initialise S at 0. Relax: A becomes 2, B becomes 5.

The closest unfinalised vertex is A at 2, so Dijkstra finalises A at distance 2 and never reconsiders it.

Then B is finalised at 5, and relaxing B→A would give — but A is already final, so the improvement is discarded.

Dijkstra reports 2; the true shortest distance to A is 1, via S→B→A.

The failure is structural, not a bug. Dijkstra's correctness proof states that when a vertex is chosen as closest, no path through any other unfinalised vertex can be shorter, because such a path must first reach that vertex at distance at least as great and then travel non-negative edges. The negative edge breaks the second clause exactly.

Bellman-Ford would handle this: after enough passes, the relaxation of B→A would reduce A to 1, because it finalises nothing early.

Example 4. Run Bellman-Ford on a graph with 4 vertices and detect whether a negative cycle exists. Edges: A→B=1, B→C=−3, C→D=2, D→B=1.

Source A, distances initialised to 0 for A and infinite elsewhere. Relax all edges times.

Pass 1: A→B gives B=1. B→C gives C=. C→D gives D=. D→B gives B=, no change.

Pass 2: A→B no change. B→C gives C=, no change. C→D gives D=0, no change. D→B gives 1, no change.

Pass 3: No changes.

Now the -th check pass: relax every edge once more and see whether anything improves. Nothing does.

No negative cycle exists. The cycle B→C→D→B has weight , which is non-negative, so circling it gains nothing.

Change C→D to weight 1, making the cycle weight . Now every pass would reduce B, C and D by 1, and the check pass would still improve them — proving a negative cycle.

The detection rule is exactly this: if any distance still improves on a -th pass, a negative cycle is reachable from the source.

Example 5. Why must Floyd-Warshall's outermost loop be over the intermediate vertex ?

The recurrence computes , the shortest path from to using only vertices through as intermediates.

Computing it requires both and — the best paths to and from using only the first intermediates — to be already correct.

Looping over outermost guarantees this, because the entire table for level is complete before any level- entry is computed.

If were the inner loop, then for a fixed pair the algorithm would try all intermediates before moving to the next pair. But a path from to through may itself need to route through some vertex that has not been considered for the sub-paths yet, so the value used for would be stale.

Concretely, with a path , computing with innermost might consider intermediate 3 before has learned about intermediate 2, and record a longer distance that is never corrected.

The looping order is the algorithm's correctness argument made executable, which is why it is the most examined implementation detail here.

Example 6. A graph has 6 vertices and 10 edges with distinct weights. How many edges does its MST have, is it unique, and does adding 5 to every weight change it?

An MST on vertices always has exactly edges, so 5 edges.

Since all weights are distinct, the MST is unique. The argument is by contradiction: if two distinct MSTs existed, take the lightest edge in one but not the other, and adding it to the second creates a cycle whose other edges are all heavier; removing the heaviest of those gives a lighter spanning tree, contradicting minimality.

Adding 5 to every edge weight does not change which tree is minimum. Every spanning tree contains exactly 5 edges, so every total rises by exactly 25, and the ordering of totals is preserved.

The same is not true for shortest paths. Paths have different edge counts, so adding a constant penalises long paths more than short ones and can change which path is shortest. That asymmetry between MST and shortest path is a standard exam contrast.

Summary

Every algorithm here is a traversal with bookkeeping, and what distinguishes them is what they record and when they dare to finalise.

BFS and DFS both cost . BFS gives unweighted shortest paths; DFS gives discovery times, finishing times and edge classification.

Topological sorting is reverse DFS finishing order, or Kahn's repeated removal of in-degree-zero vertices, which doubles as a cycle detector.

MSTs are justified by the cut and cycle properties. Kruskal sorts edges and uses union-find; Prim grows one tree with a priority queue. Both cost , and Prim with an array is better on dense graphs.

An MST is unique when all weights are distinct, has exactly edges, and is unchanged by adding or positively scaling every weight.

Dijkstra finalises the closest vertex and therefore forbids negative edges. Bellman-Ford relaxes every edge times, tolerates negative edges, and detects negative cycles by a -th pass that still improves.

Shortest paths on a DAG take by relaxing in topological order, and work with negative weights.

Floyd-Warshall is a dynamic program over permitted intermediates with the loop outermost, costing and detecting negative cycles on the diagonal. Johnson's reweights with Bellman-Ford and then runs Dijkstra everywhere, which suits sparse graphs with negative edges.

Adding a constant to every edge preserves the MST but can change the shortest path, because spanning trees have equal edge counts and paths do not.

Key formulas & results

Everything to memorise for the exam hall, in one card. Screenshot this for revision.

The organising tool
EVERY GRAPH ALGORITHM IS A TRAVERSAL WITH BOOKKEEPING. WHAT DISTINGUISHES THEM IS WHAT THEY RECORD AND WHEN THEY DARE TO FINALISE.
A GREEDY ALGORITHM FINALISES EARLY AND NEEDS A SAFETY PROOF; A DYNAMIC PROGRAM FINALISES LATE AND PAYS IN RUNNING TIME. THAT EXPLAINS EVERY PRECONDITION HERE.
Traversal costs
BREADTH-FIRST AND DEPTH-FIRST SEARCH BOTH COST O(V + E) WITH ADJACENCY LISTS AND VISIT EVERY REACHABLE VERTEX ONCE.
BFS USES A QUEUE AND GIVES UNWEIGHTED SHORTEST PATHS. DFS USES A STACK AND GIVES DISCOVERY TIMES, FINISHING TIMES AND EDGE CLASSIFICATION.
Topological sorting
LIST VERTICES IN DECREASING ORDER OF DFS FINISHING TIME, OR REPEATEDLY REMOVE A VERTEX OF IN-DEGREE ZERO AS IN KAHN'S ALGORITHM.
IF VERTICES REMAIN WHEN NO IN-DEGREE-ZERO VERTEX EXISTS, THE GRAPH HAS A CYCLE, WHICH MAKES KAHN'S ALGORITHM A CYCLE DETECTOR TOO.
The cut property
FOR ANY PARTITION OF THE VERTICES INTO TWO SETS, THE MINIMUM-WEIGHT EDGE CROSSING THE PARTITION BELONGS TO SOME MINIMUM SPANNING TREE.
THIS IS WHAT JUSTIFIES BOTH PRIM AND KRUSKAL, SINCE EACH IS CHOOSING A CHEAPEST CROSSING EDGE FOR SOME IMPLICIT CUT.
The cycle property
FOR ANY CYCLE, THE MAXIMUM-WEIGHT EDGE IN THAT CYCLE BELONGS TO NO MINIMUM SPANNING TREE.
THIS IS WHAT JUSTIFIES REJECTION IN KRUSKAL: AN EDGE CLOSING A CYCLE IS THE HEAVIEST ON THAT CYCLE, SINCE ALL LIGHTER ONES WERE ALREADY ACCEPTED.
MST algorithm costs
KRUSKAL COSTS O(E log V), DOMINATED BY THE SORT. PRIM WITH A BINARY HEAP COSTS O(E log V); PRIM WITH AN ARRAY COSTS O(V SQUARED), WHICH IS BETTER FOR DENSE GRAPHS.
AN MST HAS EXACTLY V MINUS 1 EDGES, AND IT IS UNIQUE IF ALL EDGE WEIGHTS ARE DISTINCT.
Weight transformations
ADDING A CONSTANT TO EVERY EDGE WEIGHT DOES NOT CHANGE THE MST, AND NEITHER DOES MULTIPLYING BY A POSITIVE CONSTANT.
EVERY SPANNING TREE HAS THE SAME EDGE COUNT SO ALL TOTALS SHIFT EQUALLY. SHORTEST PATHS HAVE DIFFERENT EDGE COUNTS, SO ADDING A CONSTANT CAN CHANGE WHICH IS SHORTEST.
Union-find
UNION BY RANK ATTACHES THE SHORTER TREE UNDER THE TALLER. PATH COMPRESSION REPOINTS EVERY NODE VISITED DIRECTLY AT THE ROOT.
WITH BOTH, THE AMORTISED COST IS EFFECTIVELY CONSTANT — THE INVERSE ACKERMANN FUNCTION, AT MOST 4 FOR ANY REAL INPUT. THIS IS WHY KRUSKAL IS SORT-DOMINATED.
Dijkstra's algorithm
MAINTAIN TENTATIVE DISTANCES, REPEATEDLY FINALISE THE CLOSEST UNFINALISED VERTEX, AND RELAX ITS OUTGOING EDGES. COST IS O((V + E) log V) WITH A BINARY HEAP.
IT REQUIRES NON-NEGATIVE WEIGHTS. TENTATIVE DISTANCES ARE REVISED FREELY UNTIL A VERTEX IS CHOSEN; ONLY FINALISED DISTANCES ARE GUARANTEED CORRECT.
Why Dijkstra needs non-negativity
FINALISING THE CLOSEST VERTEX IS SAFE ONLY BECAUSE ANY PATH THROUGH ANOTHER UNFINALISED VERTEX MUST FIRST REACH IT AT NO LESSER COST AND THEN TRAVEL NON-NEGATIVE EDGES.
A NEGATIVE EDGE BREAKS THE SECOND CLAUSE EXACTLY, AND THE IMPROVEMENT IS DISCARDED BECAUSE THE VERTEX IS ALREADY FINAL.
Bellman-Ford
RELAX EVERY EDGE V MINUS 1 TIMES, WHICH SUFFICES BECAUSE ANY SHORTEST PATH HAS AT MOST V MINUS 1 EDGES. COST IS O(VE).
IT TOLERATES NEGATIVE EDGES BECAUSE IT FINALISES NOTHING UNTIL ALL PASSES COMPLETE, SO A LATE IMPROVEMENT IS STILL INCORPORATED.
Negative cycle detection
IF ANY DISTANCE STILL IMPROVES ON A V-TH PASS, A NEGATIVE CYCLE IS REACHABLE FROM THE SOURCE.
NO SHORTEST PATH EXISTS IN THAT CASE, SINCE CIRCLING THE CYCLE REDUCES THE COST WITHOUT BOUND. DIJKSTRA CANNOT DETECT THIS AT ALL.
Shortest paths on a DAG
RELAX EDGES IN TOPOLOGICAL ORDER, COSTING O(V + E), AND CORRECT EVEN WITH NEGATIVE WEIGHTS.
IT BEATS BOTH DIJKSTRA AND BELLMAN-FORD, BECAUSE ACYCLICITY GUARANTEES EVERY PREDECESSOR IS FINALISED BEFORE A VERTEX IS PROCESSED.
Floyd-Warshall
d(k)[i][j] = MIN OF d(k-1)[i][j] AND d(k-1)[i][k] PLUS d(k-1)[k][j], WHERE k IS THE HIGHEST PERMITTED INTERMEDIATE VERTEX.
COST IS O(V CUBED) WITH O(V SQUARED) SPACE. A NEGATIVE VALUE ON THE DIAGONAL AFTER COMPLETION SIGNALS A NEGATIVE CYCLE.
The loop order
THE OUTERMOST LOOP MUST BE OVER k, THE INTERMEDIATE VERTEX. PUTTING IT INSIDE GIVES WRONG ANSWERS.
LOOPING OVER k OUTERMOST GUARANTEES THE ENTIRE LEVEL k MINUS 1 TABLE IS COMPLETE BEFORE ANY LEVEL k ENTRY IS COMPUTED. THIS IS THE MOST EXAMINED DETAIL HERE.
All pairs on sparse graphs
RUNNING DIJKSTRA FROM EVERY VERTEX COSTS O(V(V + E) log V), WHICH BEATS FLOYD-WARSHALL ON SPARSE GRAPHS BUT NEEDS NON-NEGATIVE WEIGHTS.
JOHNSON'S ALGORITHM REWEIGHTS WITH BELLMAN-FORD TO MAKE ALL WEIGHTS NON-NEGATIVE WHILE PRESERVING SHORTEST PATHS, THEN RUNS DIJKSTRA EVERYWHERE.
Kosaraju's algorithm
RUN DFS RECORDING FINISHING TIMES, THEN RUN DFS ON THE TRANSPOSE IN DECREASING ORDER OF THOSE TIMES. EACH TREE IN THE SECOND SEARCH IS ONE STRONGLY CONNECTED COMPONENT.
REVERSING EDGES LEAVES COMPONENTS UNCHANGED, SINCE MUTUAL REACHABILITY IS SYMMETRIC, BUT PREVENTS THE SECOND SEARCH FROM ESCAPING INTO A COMPONENT THAT FINISHES LATER.
The condensation
CONTRACTING EACH STRONGLY CONNECTED COMPONENT TO A SINGLE VERTEX YIELDS A DIRECTED ACYCLIC GRAPH.
A CYCLE AMONG COMPONENTS WOULD MAKE THEM MUTUALLY REACHABLE AND THEREFORE MERGE THEM INTO ONE, SO NO CYCLE CAN SURVIVE CONTRACTION.
The selection procedure
IS THE GRAPH WEIGHTED? IF NOT, USE BFS. ARE ANY WEIGHTS NEGATIVE? IF NOT, USE DIJKSTRA; IF SO, USE BELLMAN-FORD, OR TOPOLOGICAL RELAXATION IF ACYCLIC.
FOR ALL PAIRS: FLOYD-WARSHALL ON DENSE GRAPHS, REPEATED DIJKSTRA ON SPARSE ONES, AND JOHNSON'S ON SPARSE GRAPHS WITH NEGATIVE EDGES.
⚠️

Traps GATE sets — and how to dodge them

These are the exact option-traps and misreads that cost marks under negative marking.

WATCH OUT
Running Dijkstra on a graph with a negative edge
It finalises the closest vertex immediately, so a negative edge discovered later cannot revise that decision. The reported distance is simply wrong, not merely suboptimal, and Bellman-Ford is required.
WATCH OUT
Expecting Dijkstra to detect a negative cycle
It cannot, because it never revisits a finalised vertex and has no notion of a pass count. Only Bellman-Ford's V-th pass, or a negative Floyd-Warshall diagonal entry, detects one.
WATCH OUT
Putting the intermediate-vertex loop inside in Floyd-Warshall
The recurrence needs the entire level k minus 1 table complete before any level k entry is computed. With k innermost, sub-path values are stale and the result is wrong, though it often looks plausible.
WATCH OUT
Assuming an MST changes when a constant is added to every weight
Every spanning tree has exactly V minus 1 edges, so all totals shift by the same amount and the ordering is unchanged. Shortest paths do change, because paths have different edge counts.
WATCH OUT
Assuming the MST is always unique
It is unique only when all edge weights are distinct. With ties, several trees can achieve the same minimum total, and a question asking for the MST must then say which tie-break applies.
WATCH OUT
Using Prim with a heap on a dense graph
For a dense graph with E near V squared, the heap version costs V squared log V while the simple array version costs V squared. The array is asymptotically better precisely when the graph is dense.
WATCH OUT
Treating a tentative Dijkstra distance as final
Only distances of finalised vertices are guaranteed. A tentative value can be improved several times before its vertex is chosen, which is exactly what happens when a shorter route through a nearer vertex is found.
WATCH OUT
Relaxing edges V times in Bellman-Ford and calling it necessary
V minus 1 passes suffice, because a shortest path visits at most V vertices and therefore has at most V minus 1 edges. The V-th pass is a detection check, not part of the computation.
WATCH OUT
Using Bellman-Ford on a DAG
It is correct but wasteful. Relaxing in topological order costs O(V + E) rather than O(VE), works with negative weights, and needs only a single pass over the edges.
WATCH OUT
Forgetting union-find in Kruskal's complexity
The cycle test must be near-constant for the sort to dominate. Without union by rank and path compression a find can cost O(V), and the total becomes O(EV) rather than O(E log V).
WATCH OUT
Running Kosaraju's second pass on the original graph
The transpose is essential. Without reversing the edges, the second search escapes a component into other components it can reach, and the trees no longer correspond to strongly connected components.
WATCH OUT
Assuming a topological order is unique
It is unique only when the graph has a Hamiltonian path, meaning a total order is already forced. Otherwise many valid orders exist, and a question expecting one must specify a tie-break such as lexicographic.
WATCH OUT
Choosing Floyd-Warshall for all pairs on a sparse graph
Its V cubed cost is independent of the edge count, so on a sparse graph repeated Dijkstra at V(V+E) log V is far cheaper. Floyd-Warshall wins only when the graph is dense or has negative edges.

Exam-pattern practice

PYQ-style questions with full solutions. Work through them as a readiness check — mark yourself honestly and get your gap report at the end.

Readiness check

Are you exam-ready for Graph Algorithms?

9 problems from this chapter. Try each one, reveal the worked solution, mark yourself honestly — get your gap report at the end.

9 questions~6 min

5-minute revision

The whole chapter, distilled. Read this the night before the exam.

  • Every algorithm is a traversal with bookkeeping.
  • Preconditions follow from when an algorithm finalises.
  • BFS and DFS both cost V plus E.
  • BFS gives unweighted shortest paths.
  • DFS gives finishing times and edge classification.
  • Topological order is reverse DFS finishing time.
  • Kahn's algorithm removes in-degree-zero vertices.
  • Kahn's algorithm also detects cycles.
  • A topological order is rarely unique.
  • The cut property justifies adding a cheapest crossing edge.
  • The cycle property justifies rejecting the heaviest cycle edge.
  • An MST has exactly V minus 1 edges.
  • The MST is unique when weights are distinct.
  • Kruskal costs E log V, dominated by the sort.
  • Prim with a heap costs E log V.
  • Prim with an array costs V squared and suits dense graphs.
  • Adding a constant preserves the MST.
  • Adding a constant can change the shortest path.
  • Union by rank keeps trees shallow.
  • Path compression flattens during find.
  • Together they give near-constant amortised cost.
  • Dijkstra finalises the closest unfinalised vertex.
  • Dijkstra requires non-negative weights.
  • Tentative distances are revised until finalised.
  • Bellman-Ford relaxes every edge V minus 1 times.
  • V minus 1 suffices because paths are simple.
  • A V-th pass improvement proves a negative cycle.
  • Dijkstra cannot detect negative cycles.
  • DAG shortest paths take V plus E by topological relaxation.
  • Floyd-Warshall is a DP over permitted intermediates.
  • The k loop must be outermost.
  • Floyd-Warshall costs V cubed.
  • A negative diagonal entry signals a negative cycle.
  • Repeated Dijkstra beats Floyd-Warshall on sparse graphs.
  • Johnson's reweights then runs Dijkstra everywhere.
  • Kosaraju uses two searches and the transpose.
  • The condensation is always acyclic.

GATE question blueprint

How this topic is asked, tier by tier — so you can prep to the pattern.

Typical weightage: Algorithms contributes roughly 8-10 of the 72 core-CS marks; graph algorithms supply 2-3 of those across 2-3 questions

Question styleMarks eachTypical countWhat it tests
Algorithm selection1~1Matching stated conditions to the correct shortest-path or MST algorithm
MST properties2~1Edge counts, uniqueness and behaviour under weight transformations
MST construction2~1Tracing Prim or Kruskal and computing the total weight
Dijkstra tracing2~1Finalisation order and identifying revised tentative distances
Negative cycles2~1Why V minus 1 passes suffice and how each algorithm detects a cycle
Topological sorting2~1Producing an order and counting how many valid orders exist
Floyd-Warshall1~1Complexity, the recurrence and the loop-order requirement
Algorithm comparison2~1Choosing an all-pairs method from density and weight sign

Exam-hall strategy

Battle-tested tips from mentors and toppers for this topic under the sectional clock.

  1. Check for negative weights before choosing a shortest-path algorithm.
  2. Check density before choosing between Floyd-Warshall and repeated Dijkstra.
  3. For MST questions, remember the edge count is always V minus 1.
  4. For weight transformations, ask whether the candidates have equal edge counts.
  5. In a Dijkstra trace, record which distances were revised before finalisation.
  6. For Floyd-Warshall, verify the k loop is outermost before trusting an implementation.
  7. MST weights and path distances are commonly set as NAT, which carries no negative marking, so never leave one blank.
  8. For 1-mark and 2-mark MCQs, negative marking is -1/3 and -2/3, so guess only after eliminating an option.
  9. GATE gives a single freely-navigable 180-minute window, so flag a long algorithm trace and return to it.

Beyond the exam

Where this skill shows up in the job you're competing for — and in life.

Routing in a navigation system

Dijkstra with a priority queue is the core of every shortest-path route finder, and its non-negativity precondition is why travel times rather than elevation changes are used as weights.

Laying network cable

A minimum spanning tree is exactly the cheapest set of links connecting every site, which is why Kruskal and Prim appear in network planning tools.

Ordering a build

Topological sorting is how a build system decides compilation order, and Kahn's cycle detection is what reports a circular dependency.

Detecting arbitrage

A negative cycle in a graph of logarithmic exchange rates is a profitable currency loop, which is exactly what Bellman-Ford's V-th pass detects.

Where else this topic is tested

Prepare once, score in every exam that asks it.

GATE DAModerate overlap — graph traversals and shortest paths appear, with less emphasis on MST algorithm internals
UGC NET Computer ScienceHigh overlap — algorithm costs, preconditions and MST properties are examined as direct recall
ISRO / BARC / DRDO computer science papersVery high overlap — Dijkstra and Kruskal traces, complexity comparison and negative-cycle detection are recurring MCQ topics

Questions aspirants ask

Pulled from the Q&A community and mentor sessions.

Because Dijkstra's correctness rests on a specific argument that non-negativity makes true. When the algorithm selects the unfinalised vertex v with the smallest tentative distance d, it claims that d is already the true shortest distance. The justification is that any alternative path to v must leave the finalised set at some point, passing through an unfinalised vertex u whose tentative distance is at least d, and then continue along further edges. If those edges are non-negative, the total cannot fall below d, so no better path exists and finalising v is safe. Introduce a negative edge and the second clause fails: continuing from u can reduce the total below d, so a shorter path may exist and finalising v was premature. The algorithm never revisits v, so the improvement is discarded and the reported distance is simply wrong. A minimal counterexample makes it concrete. Source S with an edge of weight 2 to A and weight 5 to B, plus an edge of weight minus 4 from B to A. Dijkstra finalises A at 2 because 2 is smaller than 5, then finalises B at 5, and the relaxation of B to A giving 1 is rejected because A is already final. The answer 2 is wrong; the true distance is 1. The remedy is Bellman-Ford, which finalises nothing until all V minus 1 passes are complete, so a late improvement is still incorporated at cost O(VE) rather than O((V+E) log V).

Because the recurrence's meaning depends on it. The value d superscript k, subscript i j denotes the shortest path from i to j using only vertices 1 through k as intermediates. Computing it requires both d superscript k minus 1, subscript i k and d superscript k minus 1, subscript k j to be already correct — the best routes to and from k using only the earlier intermediates. Looping over k outermost guarantees exactly this, because the whole table at level k minus 1 is complete before any level k entry is touched. Put k innermost and the guarantee vanishes. For a fixed pair i and j, the algorithm would then try every intermediate in turn before moving to the next pair, so when it consults d subscript i k that value may not yet have been updated with intermediates the sub-path needs. Concretely, computing the route from 1 to 4 via intermediate 3 might read a stale value for the segment from 3 to 4 that has not yet learned it can route through 2, and record a longer distance that no later step corrects. The failure is quiet: the algorithm terminates normally and produces a distance matrix that is merely wrong in some entries, which is far worse than an obvious crash. This is why the loop order is the single most examined implementation detail in the chapter, and why a question showing three nested loops is almost always asking whether you can spot a permuted order.

By density and by whether negative edges are present. Floyd-Warshall costs V cubed regardless of how many edges exist, because its three nested loops range over vertices only. Repeated Dijkstra costs V times (V plus E) log V, which grows with the edge count. Setting the two equal and solving shows the crossover sits near E approaching V squared over log V, so for anything meaningfully sparse repeated Dijkstra wins, often by a large margin. A road network with ten thousand intersections and thirty thousand roads illustrates the gap: Floyd-Warshall needs about ten to the twelve operations while repeated Dijkstra needs about five times ten to the nine, a factor of nearly two hundred. Negative edges reverse the recommendation, because Dijkstra becomes invalid. The naive fix of adding a constant to every weight does not work, since paths have different edge counts and the adjustment changes which path is shortest. Johnson's algorithm supplies the correct fix: it computes a potential for each vertex with one Bellman-Ford run, reweights each edge so that the adjustment telescopes along any path and depends only on the endpoints, and then runs Dijkstra from every vertex on the non-negative graph. The total is O(V squared log V plus VE), retaining most of repeated Dijkstra's advantage. Two further considerations sometimes decide it. Floyd-Warshall is far simpler to implement correctly, and its output matrix at V squared entries may dominate memory either way, which is why real routing systems compute single-source paths on demand rather than materialising all pairs.

Because every spanning tree contains exactly the same number of edges, and shortest paths do not. A spanning tree on V vertices has V minus 1 edges by definition, since every vertex except the root has exactly one parent edge. Adding a constant c to every edge weight therefore increases the total of every spanning tree by exactly (V minus 1) times c. Adding the same quantity to every candidate preserves their relative ordering, so whichever tree was minimum remains minimum. The transformation is order-preserving because the edge count is invariant across candidates. Shortest paths have no such invariance. A path from S to T might use one edge or five, and adding c increases those totals by c and 5c respectively, penalising the longer path four times as much. A concrete case: a direct edge of weight 10 against a two-edge route of weight 4 plus 4. Before, the two-edge route wins at 8 against 10. Add 3 to every edge and the direct edge becomes 13 while the route becomes 7 plus 7 equals 14, so the ordering flips. This asymmetry is exactly why Johnson's algorithm cannot use a uniform constant to eliminate negative weights, and instead assigns each vertex a potential so that the adjustment along an edge from u to v is the potential of u minus the potential of v. Summed along any path, those terms telescope and leave only the endpoint potentials, so every path from S to T is adjusted identically and shortest paths are preserved.

Because a depth-first search from a vertex reaches everything that vertex can reach, which includes other components downstream of it, and the transpose is what confines the second search to a single component. Consider the condensation of the graph, formed by contracting each strongly connected component to a single vertex. It is always acyclic, since a cycle among components would make them mutually reachable and merge them. So the components form a directed acyclic graph, and there is a meaningful notion of one component being upstream of another. The first depth-first pass records finishing times. It can be shown that the component containing the vertex with the largest finishing time is a source in the condensation, meaning nothing points into it. Now run the second pass on the transpose, in decreasing order of finishing time. Reversing every edge leaves the components themselves unchanged, since mutual reachability is symmetric, but it reverses the condensation, turning the source component into a sink. Starting there, the search can reach only vertices within that component, because every edge leading out of it in the original graph now leads in. So the tree it produces is exactly one component. Remove it and repeat, and the next-highest finishing time identifies the next source in the remaining condensation. Running the second pass on the original graph instead would let the search escape the component and absorb everything downstream, producing one enormous tree rather than the components. The whole algorithm costs two traversals, so O(V plus E).
Header Logo