#line 1 "main.cpp" #include using namespace std; #include #line 2 "/home/mackerel38/kyopro/vendor/nyaan-library/shortest-path/bellman-ford.hpp" #line 2 "/home/mackerel38/kyopro/vendor/nyaan-library/graph/graph-template.hpp" template struct edge { int src, to; T cost; edge(int _to, T _cost) : src(-1), to(_to), cost(_cost) {} edge(int _src, int _to, T _cost) : src(_src), to(_to), cost(_cost) {} edge &operator=(const int &x) { to = x; return *this; } operator int() const { return to; } }; template using Edges = vector>; template using WeightedGraph = vector>; using UnweightedGraph = vector>; // Input of (Unweighted) Graph UnweightedGraph graph(int N, int M = -1, bool is_directed = false, bool is_1origin = true) { UnweightedGraph g(N); if (M == -1) M = N - 1; for (int _ = 0; _ < M; _++) { int x, y; cin >> x >> y; if (is_1origin) x--, y--; g[x].push_back(y); if (!is_directed) g[y].push_back(x); } return g; } // Input of Weighted Graph template WeightedGraph wgraph(int N, int M = -1, bool is_directed = false, bool is_1origin = true) { WeightedGraph g(N); if (M == -1) M = N - 1; for (int _ = 0; _ < M; _++) { int x, y; cin >> x >> y; T c; cin >> c; if (is_1origin) x--, y--; g[x].emplace_back(x, y, c); if (!is_directed) g[y].emplace_back(y, x, c); } return g; } // Input of Edges template Edges esgraph([[maybe_unused]] int N, int M, int is_weighted = true, bool is_1origin = true) { Edges es; for (int _ = 0; _ < M; _++) { int x, y; cin >> x >> y; T c; if (is_weighted) cin >> c; else c = 1; if (is_1origin) x--, y--; es.emplace_back(x, y, c); } return es; } // Input of Adjacency Matrix template vector> adjgraph(int N, int M, T INF, int is_weighted = true, bool is_directed = false, bool is_1origin = true) { vector> d(N, vector(N, INF)); for (int _ = 0; _ < M; _++) { int x, y; cin >> x >> y; T c; if (is_weighted) cin >> c; else c = 1; if (is_1origin) x--, y--; d[x][y] = c; if (!is_directed) d[y][x] = c; } return d; } /** * @brief グラフテンプレート * @docs docs/graph/graph-template.md */ #line 6 "/home/mackerel38/kyopro/vendor/nyaan-library/shortest-path/bellman-ford.hpp" // bellman-ford法 // goalが存在しないとき-> 負閉路が存在するときは空列を返す // goalが存在するとき -> startとgoalの間に負閉路が存在する時に負閉路を返す template vector bellman_ford(int N, Edges &es, int start = 0, int goal = -1) { T INF = numeric_limits::max() / 2; vector d(N, INF); d[start] = 0; for (int i = 0; i < N; i++) { bool update = false; for (auto &e : es) { if (d[e.src] == INF) continue; if (d[e.to] > d[e.src] + e.cost) { update = true, d[e.to] = d[e.src] + e.cost; } } if (!update) return d; } if (goal == -1) return vector(); vector negative(N, false); for (int i = 0; i < N; i++) { for (auto &e : es) { if (d[e.src] == INF) continue; if (d[e.to] > d[e.src] + e.cost) negative[e.to] = true, d[e.to] = d[e.src] + e.cost; if (negative[e.src] == true) negative[e.to] = true; } } if (negative[goal] == true) return vector(); else return d; } #line 2 "/home/mackerel38/kyopro/vendor/nyaan-library/shortest-path/dijkstra-fast.hpp" #line 2 "/home/mackerel38/kyopro/vendor/nyaan-library/data-structure/radix-heap.hpp" template struct RadixHeap { using uint = typename make_unsigned::type; static constexpr int bit = sizeof(Key) * 8; array >, bit + 1> vs; array ms; int s; uint last; RadixHeap() : s(0), last(0) { fill(begin(ms), end(ms), uint(-1)); } bool empty() const { return s == 0; } int size() const { return s; } __attribute__((target("lzcnt"))) inline uint64_t getbit(uint a) const { return 64 - _lzcnt_u64(a); } void push(const uint &key, const Val &val) { s++; uint64_t b = getbit(key ^ last); vs[b].emplace_back(key, val); ms[b] = min(key, ms[b]); } pair pop() { if (ms[0] == uint(-1)) { int idx = 1; while (ms[idx] == uint(-1)) idx++; last = ms[idx]; for (auto &p : vs[idx]) { uint64_t b = getbit(p.first ^ last); vs[b].emplace_back(p); ms[b] = min(p.first, ms[b]); } vs[idx].clear(); ms[idx] = uint(-1); } --s; auto res = vs[0].back(); vs[0].pop_back(); if (vs[0].empty()) ms[0] = uint(-1); return res; } }; /** * @brief Radix Heap * @docs docs/data-structure/radix-heap.md */ #line 2 "/home/mackerel38/kyopro/vendor/nyaan-library/graph/static-graph.hpp" namespace StaticGraphImpl { template ::value> struct E; template struct E { int to; T cost; E() {} E(const int& v, const T& c) : to(v), cost(c) {} operator int() const { return to; } }; template struct E { int to; E() {} E(const int& v) : to(v) {} operator int() const { return to; } }; template struct StaticGraph { private: template struct Es { It b, e; It begin() const { return b; } It end() const { return e; } int size() const { return int(e - b); } auto&& operator[](int i) const { return b[i]; } }; int N, M, ec; vector head; vector>> buf; vector> es; void build() { partial_sum(begin(head), end(head), begin(head)); es.resize(M); for (auto&& [u, e] : buf) es[--head[u]] = e; } public: StaticGraph(int _n, int _m) : N(_n), M(_m), ec(0), head(N + 1, 0) { buf.reserve(M); } template void add_edge(int u, Args&&... args) { #pragma GCC diagnostic ignored "-Wnarrowing" buf.emplace_back(u, E{std::forward(args)...}); #pragma GCC diagnostic warning "-Wnarrowing" ++head[u]; if ((int)buf.size() == M) build(); } Es>::iterator> operator[](int u) { return {begin(es) + head[u], begin(es) + head[u + 1]}; } const Es>::const_iterator> operator[](int u) const { return {begin(es) + head[u], begin(es) + head[u + 1]}; } int size() const { return N; } }; } // namespace StaticGraphImpl using StaticGraphImpl::StaticGraph; /** * @brief Static Graph * @docs docs/graph/static-graph.md */ #line 5 "/home/mackerel38/kyopro/vendor/nyaan-library/shortest-path/dijkstra-fast.hpp" template vector dijkstra(StaticGraph& g, int start = 0) { vector d(g.size(), T(-1)); RadixHeap Q; d[start] = 0; Q.push(0, start); while (!Q.empty()) { auto p = Q.pop(); int u = p.second; if (d[u] < T(p.first)) continue; T du = d[u]; for (auto&& [v, c] : g[u]) { if (d[v] == T(-1) || du + c < d[v]) { d[v] = du + c; Q.push(d[v], v); } } } return d; } template T dijkstra_point(StaticGraph& g, int start, int goal) { vector d(g.size(), T(-1)); RadixHeap Q; d[start] = 0; Q.push(0, start); while (!Q.empty()) { auto p = Q.pop(); int u = p.second; if(u == goal) return d[u]; if (d[u] < T(p.first)) continue; T du = d[u]; for (auto&& [v, c] : g[u]) { if (d[v] == T(-1) || du + c < d[v]) { d[v] = du + c; Q.push(d[v], v); } } } return -1; } template vector> dijkstra_restore(StaticGraph& g, int start = 0) { vector> d(g.size(), {T(-1), -1}); RadixHeap Q; d[start] = {0, -1}; Q.push(0, start); while (!Q.empty()) { auto p = Q.pop(); int u = p.second; if (d[u].first < T(p.first)) continue; T du = d[u].first; for (auto&& [v, c] : g[u]) { if (d[v].first == T(-1) || du + c < d[v].first) { d[v] = {du + c, u}; Q.push(du + c, v); } } } return d; } /* * @brief ダイクストラ法(定数倍高速化) * @docs docs/shortest-path/dijkstra-fast.md **/ #line 7 "main.cpp" using ll = long long; const ll inf = numeric_limits::max() / 2; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m; cin >> n >> m; vector p(n); for (auto& x : p) cin >> x; Edges es; vector> ori; ori.reserve(m); for (int i=0; i> u >> v >> t; u--; v--; es.emplace_back(u, v, t); ori.emplace_back(u, v, t); } for (int i=0; i(n+1, es, n); vector h(n); for (int i=0; i g(n, m); for (auto& [u, v, w] : ori) g.add_edge(u, v, w + h[u]-h[v]); ll ans = inf; ll cnt = 0; for (int s=0; s