1. DFS / Backtracking with Pruning
Intuition
Explore all paths from src to dst using DFS with depth limit k + 1 and branch-and-bound pruning on current cost.
Algorithm
- Build adjacency list from
flights. - Maintain global
minCost = infinity. - Track
visitedset to avoid infinite cycles. - Define
dfs(curr, stops, cost): - If
cost >= minCostorstops > k + 1, return. - If
curr == dst, updateminCost = min(minCost, cost), return. - For each neighbor
(nextCity, price)in adj[curr]: - If not visited[nextCity]:
- visited[nextCity] = true.
- dfs(nextCity, stops + 1, cost + price).
- visited[nextCity] = false.
- Call
dfs(src, 0, 0). - Return
minCost == infinity ? -1 : minCost.
#include <iostream>#include <vector>#include <climits>#include <algorithm> class Solution { void dfs(int curr, int dst, int k, int stops, int cost, int& minCost, const std::vector<std::vector<std::pair<int, int>>>& adj, std::vector<bool>& visited) { if (cost >= minCost) return; if (curr == dst) { minCost = cost; return; } if (stops > k) return; visited[curr] = true; for (const auto& [nextCity, price] : adj[curr]) { if (!visited[nextCity]) { dfs(nextCity, dst, k, stops + 1, cost + price, minCost, adj, visited); } } visited[curr] = false; }public: int findCheapestPrice(int n, std::vector<std::vector<int>>& flights, int src, int dst, int k) { std::vector<std::vector<std::pair<int, int>>> adj(n); for (const auto& f : flights) { adj[f[0]].push_back({f[1], f[2]}); } std::vector<bool> visited(n, false); int minCost = INT_MAX; dfs(src, dst, k, 0, 0, minCost, adj, visited); return minCost == INT_MAX ? -1 : minCost; }}; int main() { Solution sol; std::vector<std::vector<int>> flights = {{0,1,100},{1,2,100},{2,0,100},{1,3,600},{2,3,200}}; std::cout << "Cheapest price: " << sol.findCheapestPrice(4, flights, 0, 3, 1) << " (Expected: 700)\n"; return 0;}Time & Space Complexity
- Time complexity:
O(V^(K + 1)) - Space complexity:
O(V)