#pragma once #include <algorithm> #include <cassert> #include <vector> #include "Mylib/Graph/Template/graph.cpp" #include "Mylib/Math/unbounded.cpp" namespace haar_lib { template <typename T> auto bellman_ford(const graph<T> &g, int src) { using type = unbounded<T>; const int n = g.size(); std::vector<type> dist(n, type::positive_inf()); dist[src] = 0; for (int i = 0; i < n; ++i) { for (int s = 0; s < n; ++s) { for (auto &e : g[s]) { int t = e.to; T d = e.cost; if (dist[s].is_finite() and dist[t].is_finite() and dist[s].value() + d < dist[t].value() and i == n - 1) { dist[t] = type::negative_inf(); } else { if (dist[s].is_finite()) { if (dist[t].is_positive_inf()) { dist[t] = dist[s].value() + d; } else if (dist[t].is_finite()) { dist[t] = std::min(dist[t].value(), dist[s].value() + d); } } } } } } for (int i = 0; i < n; ++i) { for (int s = 0; s < n; ++s) { for (auto &e : g[s]) { if (dist[s].is_negative_inf()) { dist[e.to] = type::negative_inf(); } } } } return dist; } } // namespace haar_lib
#line 2 "Mylib/Graph/ShortestPath/bellman_ford.cpp" #include <algorithm> #include <cassert> #include <vector> #line 2 "Mylib/Graph/Template/graph.cpp" #include <iostream> #line 4 "Mylib/Graph/Template/graph.cpp" namespace haar_lib { template <typename T> struct edge { int from, to; T cost; int index = -1; edge() {} edge(int from, int to, T cost) : from(from), to(to), cost(cost) {} edge(int from, int to, T cost, int index) : from(from), to(to), cost(cost), index(index) {} }; template <typename T> struct graph { using weight_type = T; using edge_type = edge<T>; std::vector<std::vector<edge<T>>> data; auto& operator[](size_t i) { return data[i]; } const auto& operator[](size_t i) const { return data[i]; } auto begin() const { return data.begin(); } auto end() const { return data.end(); } graph() {} graph(int N) : data(N) {} bool empty() const { return data.empty(); } int size() const { return data.size(); } void add_edge(int i, int j, T w, int index = -1) { data[i].emplace_back(i, j, w, index); } void add_undirected(int i, int j, T w, int index = -1) { add_edge(i, j, w, index); add_edge(j, i, w, index); } template <size_t I, bool DIRECTED = true, bool WEIGHTED = true> void read(int M) { for (int i = 0; i < M; ++i) { int u, v; std::cin >> u >> v; u -= I; v -= I; T w = 1; if (WEIGHTED) std::cin >> w; if (DIRECTED) add_edge(u, v, w, i); else add_undirected(u, v, w, i); } } }; template <typename T> using tree = graph<T>; } // namespace haar_lib #line 3 "Mylib/Math/unbounded.cpp" template <typename T> struct unbounded { private: enum class tag_t { POSITIVE_INFINITY, NEGATIVE_INFINITY, FINITE } tag_; T value_; unbounded(tag_t tag_) : tag_(tag_) {} public: using value_type = T; unbounded() : tag_(tag_t::FINITE), value_(T()) {} unbounded(T value_) : tag_(tag_t::FINITE), value_(value_) {} unbounded(const unbounded<T>& that) : tag_(that.tag_), value_(that.value_) {} bool is_positive_inf() const { return tag_ == tag_t::POSITIVE_INFINITY; } bool is_negative_inf() const { return tag_ == tag_t::NEGATIVE_INFINITY; } bool is_finite() const { return tag_ == tag_t::FINITE; } T value() const { return value_; } T& value() { return value_; } static auto positive_inf() { return unbounded(tag_t::POSITIVE_INFINITY); } static auto negative_inf() { return unbounded(tag_t::NEGATIVE_INFINITY); } friend std::ostream& operator<<(std::ostream& s, const unbounded& a) { switch (a.tag_) { case tag_t::POSITIVE_INFINITY: s << "∞"; break; case tag_t::NEGATIVE_INFINITY: s << "-∞"; break; case tag_t::FINITE: s << a.value_; } return s; } unbounded operator-() const { if (is_finite()) return -value_; else if (is_positive_inf()) return unbounded::negative_inf(); return unbounded::positive_inf(); } auto& operator+=(unbounded that) { if (is_finite()) { if (that.is_finite()) value_ += that.value_; else tag_ = that.tag_; } return *this; } auto operator+(unbounded that) const { return unbounded(*this) += that; } auto& operator-=(unbounded that) { return (*this) += (-that); } auto operator-(unbounded that) const { return unbounded(*this) -= that; } int compare(unbounded that) const { if (is_positive_inf()) { if (that.is_positive_inf()) return 0; else return 1; } else if (is_negative_inf()) { if (that.is_negative_inf()) return 0; else return -1; } else { if (that.is_positive_inf()) return -1; else if (that.is_negative_inf()) return 1; else return (value_ > that.value_) - (value_ < that.value_); } } bool operator==(unbounded that) const { return compare(that) == 0; } bool operator!=(unbounded that) const { return compare(that) != 0; } bool operator<(unbounded that) const { return compare(that) < 0; } bool operator<=(unbounded that) const { return compare(that) <= 0; } bool operator>(unbounded that) const { return compare(that) > 0; } bool operator>=(unbounded that) const { return compare(that) >= 0; } }; #line 7 "Mylib/Graph/ShortestPath/bellman_ford.cpp" namespace haar_lib { template <typename T> auto bellman_ford(const graph<T> &g, int src) { using type = unbounded<T>; const int n = g.size(); std::vector<type> dist(n, type::positive_inf()); dist[src] = 0; for (int i = 0; i < n; ++i) { for (int s = 0; s < n; ++s) { for (auto &e : g[s]) { int t = e.to; T d = e.cost; if (dist[s].is_finite() and dist[t].is_finite() and dist[s].value() + d < dist[t].value() and i == n - 1) { dist[t] = type::negative_inf(); } else { if (dist[s].is_finite()) { if (dist[t].is_positive_inf()) { dist[t] = dist[s].value() + d; } else if (dist[t].is_finite()) { dist[t] = std::min(dist[t].value(), dist[s].value() + d); } } } } } } for (int i = 0; i < n; ++i) { for (int s = 0; s < n; ++s) { for (auto &e : g[s]) { if (dist[s].is_negative_inf()) { dist[e.to] = type::negative_inf(); } } } } return dist; } } // namespace haar_lib