✅  [python] | Simple BFS approach
The Algorithm:\n Create an adjacency list from source to target nodes along with the weight of their edges\n Create a dictionary to keep track of the current sh
**The Algorithm:**\n* Create an adjacency list from source to target nodes along with the weight of their edges\n* Create a dictionary to keep track of the current shortest time to traverse to each node in the graph (starting with infinity)\n* In a breadth first search (BFS) fashion, traverse neighbors starting at `k` until no new shortest times to a node are found\n* The maximum time to any given node after no new updates is the time it must take to traverse the whole network since each node in the network must be visited at least once\n* If the maximum is infinity, then it means that node was never updated and thus unreachable from starting node `k`\n\n---\n\n**The Code:**\n```\ndef networkDelayTime(self, times: List[List[int]], n: int, k: int) -> int:\n    \n\t# establish graph and data structures\n\ttotal_time_to_reach_node = {i: float(\'inf\') for i in range(1, n+1)}\n\tgraph = defaultdict(list)\n\tfor src, target, time in times:\n\t\tif src in graph: \n\t\t\tgraph[src].append((target, time))\n\t\telse:\n\t\t\tgraph[src] = [(target, time)]\n\n\tqueue = [(k, 0)]\n\n\t# bfs until no new updates are made\n\twhile queue:\n\t\tsrc, total_time = queue.pop(0)\n\t\tif total_time < total_time_to_reach_node[src]:\n\t\t\ttotal_time_to_reach_node[src] = total_time\n\t\t\tfor target, time in graph[src]:\n\t\t\t\tqueue.append((target, total_time + time))    \n\n\t# if possible, return the total time to traverse network\n\ttime_to_traverse_network = max(total_time_to_reach_node.values())\n\tif time_to_traverse_network < float(\'inf\'):\n\t\treturn time_to_traverse_network\n\telse:\n\t\treturn -1\n```
['Breadth-First Search', 'Python']