From 364d7d28a268560fde0a1a8a07a886170a45a12d Mon Sep 17 00:00:00 2001 From: kekeandzeyu Date: Mon, 26 Aug 2024 16:31:45 +0800 Subject: [PATCH] Add more notes in Data Structures and Algorithms! --- .../Data-Structures-and-Algorithms-2.md | 251 +++++++++++++++++- 1 file changed, 249 insertions(+), 2 deletions(-) diff --git a/Writerside/topics/Data-Structures-and-Algorithms-2.md b/Writerside/topics/Data-Structures-and-Algorithms-2.md index 69a24f8..272867c 100644 --- a/Writerside/topics/Data-Structures-and-Algorithms-2.md +++ b/Writerside/topics/Data-Structures-and-Algorithms-2.md @@ -6163,6 +6163,254 @@ rowspan="2">No Negative CyclesEV +

Java

+ +```Java +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +public class BellmanFordSP { + private final double[] distTo; + private final DirectedEdge[] edgeTo; + private final boolean[] onQueue; + private final int[] cost; + private final int s; + private boolean hasNegativeCycle; + + private final Queue q; + + public BellmanFordSP(EdgeWeightedDigraph G, int s) { + this.s = s; + distTo = new double[G.V()]; + edgeTo = new DirectedEdge[G.V()]; + onQueue = new boolean[G.V()]; + cost = new int[G.V()]; + for (int v = 0; v < G.V(); v++) + distTo[v] = Double.POSITIVE_INFINITY; + distTo[s] = 0.0; + + q = new LinkedList<>(); + q.add(s); + onQueue[s] = true; + + while (!q.isEmpty()) { + int v = q.remove(); + onQueue[v] = false; + relax(G, v); + } + } + + private void relax(EdgeWeightedDigraph G, int v) { + for (DirectedEdge e : G.adj(v)) { + int w = e.to(); + if (distTo[w] > distTo[v] + e.weight()) { + distTo[w] = distTo[v] + e.weight(); + edgeTo[w] = e; + cost[w]++; + + if (!onQueue[w]) { + q.add(w); + onQueue[w] = true; + } + + if (cost[w] >= G.V()) { + hasNegativeCycle = true; + return; + } + } + } + } + + public double distTo(int v) { + return distTo[v]; + } + + public boolean hasPathTo(int v) { + return distTo[v] < Double.POSITIVE_INFINITY; + } + + public Iterable pathTo(int v) { + if (!hasPathTo(v)) return null; + List path = new ArrayList<>(); + for (DirectedEdge e = edgeTo[v]; e != null; e = edgeTo[e.from()]) { + path.add(e); + } + return path; + } + + public boolean hasNegativeCycle() { + return hasNegativeCycle; + } +} +``` + +

C++ (BellmanFordSP.h)

+ +```C++ +#ifndef BELLMANFORDSP_H +#define BELLMANFORDSP_H + +#include "EdgeWeightedDigraph.h" +#include +#include + +class BellmanFordSP { +private: + std::vector distTo; // distTo[v] = distance of shortest s->v path + std::vector edgeTo; // edgeTo[v] = last edge on shortest s->v path + std::vector onQueue; // onQueue[v] = is v on the queue? + std::vector cost; // cost[v] = number of relaxations performed on v + int s; // source vertex + bool hasNegativeCycle; // flag to detect negative cycle + + std::queue q; + +public: + BellmanFordSP(const EdgeWeightedDigraph& G, int s); + [[nodiscard]] double getdistTo(int v) const; + [[nodiscard]] bool hasPathTo(int v) const; + [[nodiscard]] std::vector pathTo(int v) const; + [[nodiscard]] bool NegativeCycle() const; + +private: + void relax(const EdgeWeightedDigraph& G, int v); +}; + +#endif // BELLMANFORDSP_H +``` + +

C++ (BellmanFordSP.cpp)

+ +```C++ +#include "BellmanFordSP.h" +#include + +BellmanFordSP::BellmanFordSP(const EdgeWeightedDigraph& G, const int s) : + distTo(G.getV(), std::numeric_limits::infinity()), + edgeTo(G.getV(), DirectedEdge(-1, -1, 0.0)), + onQueue(G.getV(), false), + cost(G.getV(), 0), + s(s), + hasNegativeCycle(false) { + + distTo[s] = 0.0; + q.push(s); + onQueue[s] = true; + + while (!q.empty()) { + int v = q.front(); + q.pop(); + onQueue[v] = false; + relax(G, v); + } +} + +double BellmanFordSP::getdistTo(const int v) const { + return distTo[v]; +} + +bool BellmanFordSP::hasPathTo(const int v) const { + return distTo[v] < std::numeric_limits::infinity(); +} + +std::vector BellmanFordSP::pathTo(const int v) const { + if (!hasPathTo(v)) { + return {}; + } + std::vector path; + for (DirectedEdge e = edgeTo[v]; e.from() != -1; e = edgeTo[e.from()]) { + path.push_back(e); + } + return path; +} + +bool BellmanFordSP::NegativeCycle() const { + return hasNegativeCycle; +} + +void BellmanFordSP::relax(const EdgeWeightedDigraph& G, const int v) { + for (const DirectedEdge& e : G.getAdj(v)) { + int w = e.to(); + if (distTo[w] > distTo[v] + e.getWeight()) { + distTo[w] = distTo[v] + e.getWeight(); + edgeTo[w] = e; + cost[w]++; + + if (!onQueue[w]) { + q.push(w); + onQueue[w] = true; + } + + if (cost[w] >= G.getV()) { + hasNegativeCycle = true; + return; + } + } + } +} +``` + +

Python

+ +```Python +from EdgeWeightedDigraph import EdgeWeightedDigraph + +class BellmanFordSP: + def __init__(self, G, s): + self.distTo = [float("inf") for _ in range(G.get_V())] + self.edgeTo = [None for _ in range(G.get_V())] + self.onQueue = [False for _ in range(G.get_V())] + self.cost = [0 for _ in range(G.get_V())] + self.s = s + self.hasNegativeCycle = False + + self.distTo[s] = 0.0 + self.q = [s] + self.onQueue[s] = True + + while self.q: + v = self.q.pop(0) + self.onQueue[v] = False + self.relax(G, v) + + def distTo(self, v): + return self.distTo[v] + + def hasPathTo(self, v): + return self.distTo[v] != float("inf") + + def pathTo(self, v): + if not self.hasPathTo(v): + return None + path = [] + e = self.edgeTo[v] + while e is not None: + path.append(e) + e = self.edgeTo[e.from_vertex()] + return path + + def hasNegativeCycle(self): + return self.hasNegativeCycle + + def relax(self, G, v): + for e in G.get_adj(v): + w = e.to_vertex() + if self.distTo[w] > self.distTo[v] + e.get_weight(): + self.distTo[w] = self.distTo[v] + e.get_weight() + self.edgeTo[w] = e + self.cost[w] += 1 + + if not self.onQueue[w]: + self.q.append(w) + self.onQueue[w] = True + + if self.cost[w] >= G.get_V(): + self.hasNegativeCycle = True + return +``` +

Find A Negative Cycle:

If there is a negative cycle, Bellman-Ford gets stuck in loop, @@ -6205,5 +6453,4 @@ cycle (and can trace back edgeTo[v] entries to find it).

-## 18 Maximum Flow and Minimum Cut - +## 18 Maximum Flow and Minimum Cut \ No newline at end of file