1. DFS / Exhaustive Path Search
Intuition
Explore all possible simple directed paths from source k to every other node using Depth-First Search. Maintain an array dist where dist[v] stores the minimum time found so far to reach node v. If a newly explored path reaches v in less time, update dist[v] and recursively explore neighbors. Due to cycles and alternate paths, an unpruned DFS may explore exponentially many paths.
Algorithm
- Construct an adjacency list for the directed edges.
- Initialize
distarray of size n + 1 with infinity, setdist[k] = 0. - Define
dfs(u, current_time): - If
current_time >= dist[u], return (pruning). -
dist[u] = current_time. - For each outgoing edge
(v, weight)from u: -
dfs(v, current_time + weight). - Run
dfs(k, 0). - Find the maximum value among
dist[1..n]. If any node has infinity, return -1; otherwise return max time.
#include <iostream>#include <vector>#include <algorithm>#include <climits> void dfs(int u, int timeSoFar, const std::vector<std::vector<std::pair<int, int>>>& adj, std::vector<int>& dist) { if (timeSoFar >= dist[u]) return; dist[u] = timeSoFar; for (const auto& [v, w] : adj[u]) { dfs(v, timeSoFar + w, adj, dist); }} int networkDelayTimeDFS(std::vector<std::vector<int>>& times, int n, int k) { std::vector<std::vector<std::pair<int, int>>> adj(n + 1); for (const auto& t : times) { adj[t[0]].push_back({t[1], t[2]}); } std::vector<int> dist(n + 1, INT_MAX); dfs(k, 0, adj, dist); int maxTime = 0; for (int i = 1; i <= n; ++i) { if (dist[i] == INT_MAX) return -1; maxTime = std::max(maxTime, dist[i]); } return maxTime;} int main() { std::vector<std::vector<int>> times = {{2,1,1},{2,3,1},{3,4,1}}; std::cout << "Delay Time DFS: " << networkDelayTimeDFS(times, 4, 2) << std::endl; return 0;}Time & Space Complexity
- Time complexity:
O(V!) in the worst-case on dense DAGs/cyclic graphs where multiple paths of varying lengths are explored repeatedly. - Space complexity:
O(V) for the recursion stack and distance tracking array.