Find cycle of shortest length in a directed graph with positive weights
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Finding the cycle of shortest length in a directed graph with positive weights is an important problem in graph theory and algorithms. It appears in networks where you need to detect the smallest feedback loop, such as routing cycles in networks, deadlock detection in resource allocation graphs, or identifying the shortest periodic pattern in a state machine. The challenge is to find a cycle (a path that returns to its starting node) whose total edge weight is minimized.
Problem Definition
Given a directed graph where is a set of vertices and is a set of directed edges, each edge has a positive weight . The goal is to find a cycle such that the total weight is minimized over all cycles in the graph.
Key Concepts
Graph Representation
A directed graph can be represented using an adjacency matrix or an adjacency list.
- Adjacency matrix: A 2D array where entry stores the weight of edge , or if no edge exists.
- Adjacency list: Each vertex stores a list of its outgoing edges and their weights. More memory-efficient for sparse graphs.
Why Positive Weights Matter
Positive weights guarantee that no negative-weight cycle exists. This is important because algorithms like Floyd-Warshall and Dijkstra rely on this property for correctness. With positive weights, every cycle has a strictly positive total weight, and the shortest cycle is well-defined.
Algorithmic Approaches
Approach 1: Floyd-Warshall Adaptation
The Floyd-Warshall algorithm computes shortest paths between all pairs of vertices. We can adapt it to find the shortest cycle.
Initialization: Set up a distance matrix where if edge exists, and otherwise. Crucially, set (not zero) because we want the shortest path from back to through at least one other vertex.
Distance Update: Apply the standard triple-nested loop:
for each intermediate vertex .
Shortest Cycle: After the algorithm completes, the shortest cycle length is:
The minimum diagonal entry gives the weight of the shortest cycle.
Complexity: time and space. This is practical for dense graphs with moderate vertex counts.
Approach 2: Dijkstra from Each Vertex
For sparse graphs, running Dijkstra's algorithm from each vertex can be more efficient.
For each vertex :
- Run Dijkstra's shortest path from .
- For each incoming edge with weight , compute . This gives the shortest cycle through that uses edge as its final edge.
- Track the minimum across all vertices.
Complexity: with a binary heap. For sparse graphs where , this beats Floyd-Warshall.
Approach 3: DFS-Based Cycle Detection with Weight Tracking
A depth-first search can find cycles by detecting back edges. During DFS, maintain a stack of vertices in the current path along with cumulative weights. When a back edge is found (an edge to a vertex already on the current stack), compute the cycle weight as the difference in cumulative weights plus the back edge weight.
This approach does not guarantee finding the globally shortest cycle in a single pass, but it can be used as a heuristic or combined with iterating over all starting vertices.
Worked Example
Consider a directed graph with these weighted edges:
| From | To | Weight |
| A | B | 1 |
| B | C | 2 |
| C | A | 1 |
| C | D | 3 |
| D | B | 4 |
Cycles in this graph:
- A to B to C to A: weight =
- B to C to D to B: weight =
Using Floyd-Warshall, initialize the distance matrix with edge weights and on the diagonal:
| A | B | C | D | |
| A | 1 | |||
| B | 2 | |||
| C | 1 | 3 | ||
| D | 4 |
After running the algorithm, the diagonal entries become: , , , . The shortest cycle has weight , which corresponds to A to B to C to A.
Comparison of Approaches
| Approach | Time Complexity | Best For | ||||||
| Floyd-Warshall | `$O( | V | ^3)$` | Dense graphs, small to medium `$ | V | $` | ||
| Dijkstra per vertex | `$O( | V | \cdot | E | \log | V | )$` | Sparse graphs |
| DFS-based | `$O( | V | + | E | )$` per run | Heuristic or when any cycle suffices |
Practical Considerations
- No cycle exists: If the graph is a DAG (directed acyclic graph), there are no cycles. Floyd-Warshall will leave all diagonal entries at , and Dijkstra will never find a path from any vertex back to itself.
- Reconstructing the cycle: To find the actual vertices in the shortest cycle (not just the weight), maintain a predecessor matrix during Floyd-Warshall or a predecessor array during Dijkstra. Trace back from the diagonal entry to reconstruct the path.
- Self-loops: A self-loop with weight is technically a cycle of length 1. If self-loops should be excluded, skip diagonal entries that come directly from a single edge.
Summary
Finding the shortest cycle in a directed graph with positive weights can be solved by adapting Floyd-Warshall (set diagonal to initially, then read the minimum diagonal entry after completion) or by running Dijkstra from each vertex and checking for paths back to the source. Floyd-Warshall is simpler to implement and works well for dense graphs at , while the Dijkstra approach scales better for sparse graphs. Both approaches are correct because positive edge weights guarantee no negative cycles.

