From c3ff7fb18d5a0293b4bdfb53eff1567af057af78 Mon Sep 17 00:00:00 2001 From: Vallari Agrawal Date: Sun, 28 Jul 2024 10:52:08 +0000 Subject: [PATCH] GITBOOK-48: Describe Bellman and Dijkstra algo --- data-structures/graphs/shortest-path.md | 53 +++++++++++++++++++------ data-structures/heaps.md | 4 +- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/data-structures/graphs/shortest-path.md b/data-structures/graphs/shortest-path.md index 217e38f..195a699 100644 --- a/data-structures/graphs/shortest-path.md +++ b/data-structures/graphs/shortest-path.md @@ -2,22 +2,34 @@ Shorted Path Algorithms: +Negative cycles -> where the sum of the edges in a cycle is negative. It's not possible to find shortest path with negative cycles. Question would usually ask to "detect" it only. Only Bellman Ford can detect with negative cycles. + +Let `u` be source node, `v` be destination node, `w` be weight of the edge between the `u` and `v`. + ### [Bellman Ford](https://www.programiz.com/dsa/bellman-ford-algorithm) **Time**: `O(VE)` **Space**: `O(N)` Bellman Ford algorithm helps us find **the shortest path from a vertex to all other vertices** of a weighted graph. -```python -def networkDelayTime(self, times: List[List[int]], N: int, K: int) -> int: - dist = [float("inf") for _ in range(N)] +* Uses edges as inputs `[[u, v, w]]` +* Slower than Dijkstra +* Able to use negative edges. +* Used to detected negative cycles. (If Nth iteration of loop determines negative-cycles) + +
def networkDelayTime(self, times: List[List[int]], N: int, K: int) -> int:
+        dist = [float("inf") for _ in range(N)]
         dist[K-1] = 0
         for _ in range(N-1):
             for u, v, w in times:
-                if dist[u-1] + w < dist[v-1]:
+                if dist[u-1] + w < dist[v-1]:
                     dist[v-1] = dist[u-1] + w
+        # nth loop determines negative cycles
+        for u, v, w in times:
+            if dist[u-1] + w < dist[v-1]:
+                return None # negative cycles detected!
         return dist
-```
+
### [Dijkstra](https://www.programiz.com/dsa/dijkstra-algorithm) @@ -25,12 +37,18 @@ def networkDelayTime(self, times: List[List[int]], N: int, K: int) -> int: Dijkstra's algorithm allows us to find **the** **shortest path between any two vertices of a graph**. -Implementation can be done in naive way and easy way (with heaps - given below) \[[read here](https://pythonalgos.com/dijkstras-algorithm-in-5-steps-with-python/)] +* Input has to be changed to `{u:{v: w}}` +* Only for non-negative edges. +* Don't work with negative cycles. +* Differs from the minimum spanning tree because the shortest distance between two vertices might not include all the vertices of the graph. -```python - def dijkstra(self, times: List[List[int]], root, destination) -> int: - pyth weight = collections.defaultdict(dict) - for u, v, w in times: +[https://www.youtube.com/watch?v=EaphyqKU4PQ](https://www.youtube.com/watch?v=EaphyqKU4PQ) + +Implementation can be done in naive way and easy way (with min-heaps/pq - given below) \[[read here](https://pythonalgos.com/dijkstras-algorithm-in-5-steps-with-python/)] + +
 def dijkstra(self, times: List[List[int]], root, destination) -> int:
+        weight = collections.defaultdict(dict)
+        for u, v, w in times:
             weight[u][v] = w
         heap = [(0, root)]
         dist = {}
@@ -41,13 +59,16 @@ Implementation can be done in naive way and easy way (with heaps - given below)
                 for v in weight[u]:
                     heapq.heappush(heap, (dist[u] + weight[u][v], v))
         return dist[destination]
-```
+
### [Floyd Warshall](https://www.programiz.com/dsa/floyd-warshall-algorithm) **Time**: `O(V^3)` **Space**: `O(V^2)` -Floyd-Warshall Algorithm is an algorithm for finding **the shortest path between all the pairs of vertices** in a weighted graph. This algorithm works for both the directed and undirected weighted graphs. But, it does not work for the graphs with negative cycles (where the sum of the edges in a cycle is negative). +Floyd-Warshall Algorithm is an algorithm for finding **the shortest path between all the pairs of vertices** in a weighted graph. + +* Works for both the directed and undirected weighted graphs. +* Does not work for the graphs with negative cycles. ```python def networkDelayTime(self, times: List[List[int]], N: int, K: int) -> int: @@ -89,6 +110,14 @@ Floyd-Warshall Algorithm is an algorithm for finding **the shortest path between +*** + +### Comparing + +* It is similar to Dijkstra's algorithm but it can work with graphs in which edges can have negative weights. Dijkstra's algorithm has better time complexity than BF. + + + ### Resources * Understand algorithms from Programiz (click on algo heading above) diff --git a/data-structures/heaps.md b/data-structures/heaps.md index ec47a1f..a0c5079 100644 --- a/data-structures/heaps.md +++ b/data-structures/heaps.md @@ -26,7 +26,7 @@ Basic Functions: * `heapq.heapify(list)` * `heapq.heappush`(_heap_, _item_) -* `heapq.heappop`(_heap_) +* `heapq.heappop`(_heap_) - returns smallest * `heapq.nlargest`(_n_, _iterable_, _key=None_) * `heapq.nsmallest`(_n_, _iterable_, _key=None_) @@ -47,7 +47,7 @@ class MaxHeap: def push(self, item): heapq.heappush(self.heap, -item) - def pop(self): + def pop(self): # returns largest popped = heapq.heappop(self.heap) return -popped