This documentation is automatically generated by competitive-verifier/competitive-verifier
// competitive-verifier: PROBLEM https://onlinejudge.u-aizu.ac.jp/problems/GRL_1_B
#include <algorithm>
#include <iostream>
#include <limits>
#include "tools/bellman_ford.hpp"
int main() {
std::cin.tie(nullptr);
std::ios_base::sync_with_stdio(false);
int N, M, r;
std::cin >> N >> M >> r;
tools::bellman_ford<int> graph(N);
for (int i = 0; i < M; ++i) {
int s, t, d;
std::cin >> s >> t >> d;
graph.add_edge(s, t, d);
}
const auto dist = graph.query(r);
if (std::ranges::find(dist, std::numeric_limits<int>::min()) != dist.end()) {
std::cout << "NEGATIVE CYCLE" << '\n';
} else {
for (const auto d : dist) {
if (d == std::numeric_limits<int>::max()) {
std::cout << "INF" << '\n';
} else {
std::cout << d << '\n';
}
}
}
return 0;
}
#line 1 "tests/bellman_ford.test.cpp"
// competitive-verifier: PROBLEM https://onlinejudge.u-aizu.ac.jp/problems/GRL_1_B
#include <algorithm>
#include <iostream>
#include <limits>
#line 1 "tools/bellman_ford.hpp"
#include <cassert>
#include <iterator>
#line 7 "tools/bellman_ford.hpp"
#include <utility>
#include <vector>
#line 1 "tools/chmin.hpp"
#include <type_traits>
#line 6 "tools/chmin.hpp"
namespace tools {
template <typename M, typename N>
bool chmin(M& lhs, const N& rhs) {
bool updated;
if constexpr (::std::is_integral_v<M> && ::std::is_integral_v<N>) {
updated = ::std::cmp_less(rhs, lhs);
} else {
updated = rhs < lhs;
}
if (updated) lhs = rhs;
return updated;
}
}
#line 1 "tools/shortest_path_tree.hpp"
#line 7 "tools/shortest_path_tree.hpp"
#include <ranges>
#line 10 "tools/shortest_path_tree.hpp"
namespace tools {
template <typename Cost, typename F>
class shortest_path_tree {
::std::vector<Cost> m_dist;
::std::vector<int> m_from;
F m_get_vertex;
public:
shortest_path_tree() = default;
template <::std::ranges::range R1, ::std::ranges::range R2>
shortest_path_tree(R1&& d, R2&& p, const F& f) : m_get_vertex(f) {
::std::ranges::copy(d, ::std::back_inserter(this->m_dist));
::std::ranges::copy(p, ::std::back_inserter(this->m_from));
assert(this->m_dist.size() == this->m_from.size());
assert(::std::ranges::all_of(this->m_from, [](const auto p_i) { return p_i >= -1; }));
}
int size() const {
return this->m_dist.size();
}
const ::std::vector<Cost>& dist() const & {
return this->m_dist;
}
::std::vector<Cost> dist() && {
return ::std::move(this->m_dist);
}
Cost dist(const int v) const {
assert(0 <= v && v < this->size());
return this->m_dist[v];
}
int from_vertex(const int v) const {
assert(0 <= v && v < this->size());
return this->m_from[v] >= 0 ? this->m_get_vertex(this->m_from[v], v) : -1;
}
int from_edge_id(const int v) const {
assert(0 <= v && v < this->size());
return this->m_from[v];
}
::std::vector<int> vertex_path(const int v) const {
assert(0 <= v && v < this->size());
::std::vector<int> path;
for (int u = v; u >= 0; u = this->from_vertex(u)) {
path.push_back(u);
}
::std::ranges::reverse(path);
return path;
}
::std::vector<int> edge_id_path(const int v) const {
assert(0 <= v && v < this->size());
::std::vector<int> path;
for (int u = v; this->m_from[u] >= 0; u = this->from_vertex(u)) {
path.push_back(this->m_from[u]);
}
::std::ranges::reverse(path);
return path;
}
};
template <::std::ranges::range R1, ::std::ranges::range R2, typename F>
shortest_path_tree(R1&&, R2&&, const F&) -> shortest_path_tree<::std::ranges::range_value_t<R1>, F>;
}
#line 11 "tools/bellman_ford.hpp"
namespace tools {
template <typename T>
class bellman_ford {
public:
struct edge {
int from;
int to;
T cost;
};
private:
int m_size;
::std::vector<edge> m_edges;
public:
bellman_ford() = default;
explicit bellman_ford(const int n) : m_size(n) {
}
int size() const {
return this->m_size;
}
int add_edge(const int u, const int v, const T w) {
assert(0 <= u && u < this->size());
assert(0 <= v && v < this->size());
this->m_edges.push_back({u, v, w});
return this->m_edges.size() - 1;
}
const edge& get_edge(const int k) const & {
assert(0 <= k && k < ::std::ssize(this->m_edges));
return this->m_edges[k];
}
edge get_edge(const int k) && {
assert(0 <= k && k < ::std::ssize(this->m_edges));
return ::std::move(this->m_edges[k]);
}
const ::std::vector<edge>& edges() const & {
return this->m_edges;
}
::std::vector<edge> edges() && {
return ::std::move(this->m_edges);
}
template <bool Restore = false>
auto query(const int s) const {
assert(0 <= s && s < this->size());
::std::vector<T> dist(this->size(), ::std::numeric_limits<T>::max());
dist[s] = 0;
::std::vector<int> prev(Restore ? this->size() : 0, -1);
for (int i = 0; i + 1 < this->size(); ++i) {
for (int k = 0; k < ::std::ssize(this->m_edges); ++k) {
const auto& edge = this->m_edges[k];
if (dist[edge.from] < ::std::numeric_limits<T>::max() && ::tools::chmin(dist[edge.to], dist[edge.from] + edge.cost)) {
if constexpr (Restore) {
prev[edge.to] = k;
}
}
}
}
for (int k = 0; k < ::std::ssize(this->m_edges); ++k) {
const auto& edge = this->m_edges[k];
if (dist[edge.from] < ::std::numeric_limits<T>::max() && dist[edge.from] + (dist[edge.from] > ::std::numeric_limits<T>::lowest() ? edge.cost : 0) < dist[edge.to]) {
dist[edge.to] = ::std::numeric_limits<T>::lowest();
if constexpr (Restore) {
prev[edge.to] = -1;
}
}
}
for (int i = 0; i + 1 < this->size(); ++i) {
for (int k = 0; k < ::std::ssize(this->m_edges); ++k) {
const auto& edge = this->m_edges[k];
if (dist[edge.from] < ::std::numeric_limits<T>::max() && ::tools::chmin(dist[edge.to], dist[edge.from] + (dist[edge.from] > ::std::numeric_limits<T>::lowest() ? edge.cost : 0))) {
if constexpr (Restore) {
prev[edge.to] = -1;
}
}
}
}
if constexpr (Restore) {
return ::tools::shortest_path_tree(dist, prev, [&](const auto e, auto) {
return this->m_edges[e].from;
});
} else {
return dist;
}
}
};
}
#line 7 "tests/bellman_ford.test.cpp"
int main() {
std::cin.tie(nullptr);
std::ios_base::sync_with_stdio(false);
int N, M, r;
std::cin >> N >> M >> r;
tools::bellman_ford<int> graph(N);
for (int i = 0; i < M; ++i) {
int s, t, d;
std::cin >> s >> t >> d;
graph.add_edge(s, t, d);
}
const auto dist = graph.query(r);
if (std::ranges::find(dist, std::numeric_limits<int>::min()) != dist.end()) {
std::cout << "NEGATIVE CYCLE" << '\n';
} else {
for (const auto d : dist) {
if (d == std::numeric_limits<int>::max()) {
std::cout << "INF" << '\n';
} else {
std::cout << d << '\n';
}
}
}
return 0;
}
Env | Name | Status | Elapsed | Memory |
---|---|---|---|---|
g++ | 00_sample_00.in |
![]() |
5 ms | 4 MB |
g++ | 00_sample_01.in |
![]() |
4 ms | 4 MB |
g++ | 00_sample_02.in |
![]() |
4 ms | 4 MB |
g++ | 01_small_00.in |
![]() |
4 ms | 4 MB |
g++ | 01_small_01.in |
![]() |
4 ms | 4 MB |
g++ | 02_corner_00.in |
![]() |
4 ms | 4 MB |
g++ | 02_corner_01.in |
![]() |
4 ms | 4 MB |
g++ | 02_corner_02.in |
![]() |
4 ms | 4 MB |
g++ | 02_corner_03.in |
![]() |
4 ms | 4 MB |
g++ | 02_corner_04.in |
![]() |
4 ms | 4 MB |
g++ | 02_corner_05.in |
![]() |
4 ms | 4 MB |
g++ | 02_corner_06.in |
![]() |
4 ms | 4 MB |
g++ | 03_medium_00.in |
![]() |
4 ms | 4 MB |
g++ | 03_medium_01.in |
![]() |
4 ms | 4 MB |
g++ | 03_medium_02.in |
![]() |
4 ms | 4 MB |
g++ | 03_medium_03.in |
![]() |
4 ms | 3 MB |
g++ | 04_rand_00.in |
![]() |
4 ms | 4 MB |
g++ | 04_rand_01.in |
![]() |
4 ms | 4 MB |
g++ | 04_rand_02.in |
![]() |
4 ms | 4 MB |
g++ | 04_rand_03.in |
![]() |
4 ms | 4 MB |
g++ | 04_rand_04.in |
![]() |
4 ms | 4 MB |
g++ | 04_rand_05.in |
![]() |
4 ms | 4 MB |
g++ | 04_rand_06.in |
![]() |
4 ms | 4 MB |
g++ | 04_rand_07.in |
![]() |
5 ms | 4 MB |
g++ | 05_dag_00.in |
![]() |
4 ms | 4 MB |
g++ | 05_dag_01.in |
![]() |
4 ms | 4 MB |
g++ | 05_dag_02.in |
![]() |
4 ms | 4 MB |
g++ | 05_dag_03.in |
![]() |
4 ms | 4 MB |
g++ | 06_ring_00.in |
![]() |
5 ms | 4 MB |
g++ | 06_ring_01.in |
![]() |
4 ms | 4 MB |
g++ | 06_ring_02.in |
![]() |
4 ms | 4 MB |
g++ | 06_ring_03.in |
![]() |
4 ms | 4 MB |
g++ | 07_large_00.in |
![]() |
4 ms | 4 MB |
g++ | 07_large_01.in |
![]() |
5 ms | 4 MB |
g++ | 07_large_02.in |
![]() |
4 ms | 4 MB |
g++ | 07_large_03.in |
![]() |
4 ms | 4 MB |
g++ | 08_maximum_00.in |
![]() |
5 ms | 4 MB |
g++ | 08_maximum_01.in |
![]() |
7 ms | 4 MB |
g++ | 08_maximum_02.in |
![]() |
7 ms | 4 MB |
g++ | 08_maximum_03.in |
![]() |
8 ms | 4 MB |