Skip to main content
Back to problems
#847
Hard Algorithms

Shortest path visiting all nodes

Dynamic Programming Bit Manipulation Breadth-First Search Graph Theory Bitmask
65.8% acceptance
Feb 22, 2026
4614
181
You have an undirected, connected graph of n nodes labeled from 0 to n - 1. You are given an array graph where graph[i] is a list of all the nodes connected with node i by an edge. Return the length of the shortest path that visits every node. You may start and stop at any node, you may revisit nodes multiple times, and you may reuse edges.

Solution

Rust
Time O(n * m)
Space O(n * m)
LeetCode
solution.rs
/*
 * You have an undirected, connected graph of n nodes labeled from 0 to n - 1. You are given an array graph where graph[i] is a list of all the nodes connected with node i by an edge.
 * Return the length of the shortest path that visits every node. You may start and stop at any node, you may revisit nodes multiple times, and you may reuse edges.
 * Example 1:
 * Input: graph = [[1,2,3],[0],[0],[0]]
 * Output: 4
 * Explanation: One possible path is [1,0,2,0,3]
 * Example 2:
 * Input: graph = [[1],[0,2,4],[1,3,4],[2],[1,2]]
 * Output: 4
 * Explanation: One possible path is [0,1,4,2,3]
 * Constraints:
 * n == graph.length
 * 1 <= n <= 12
 * 0 <= graph[i].length < n
 * graph[i] does not contain i.
 * If graph[a] contains b, then graph[b] contains a.
 * The input graph is always connected.
 */

use std::collections::VecDeque;
impl Solution {
  pub fn shortest_path_length(graph: Vec<Vec<i32>>) -> i32 {
    let n = graph.len();
    let full = (1 << n) - 1;
    let mut visited = vec![vec![false; 1 << n]; n];
    let mut queue = VecDeque::new();
    for i in 0..n {
      let mask = 1 << i;
      queue.push_back((i, mask, 0i32));
      visited[i][mask] = true;
    }
    while let Some((node, mask, dist)) = queue.pop_front() {
      if mask == full { return dist; }
      for &next in &graph[node] {
        let next = next as usize;
        let new_mask = mask | (1 << next);
        if !visited[next][new_mask] {
          visited[next][new_mask] = true;
          queue.push_back((next, new_mask, dist + 1));
        }
      }
    }
    0
  }
}