結果

問題 No.3653 Space-Time Courier
コンテスト
ユーザー ぽえ
提出日時 2026-08-28 21:47:33
言語 C++23
(gcc 15.2.0 + boost 1.90.0)
コンパイル:
g++-15 -O2 -lm -std=c++23 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
AC  
実行時間 266 ms / 4,000 ms
+ 234µs
コード長 9,504 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 3,803 ms
コンパイル使用メモリ 460,084 KB
実行使用メモリ 6,272 KB
最終ジャッジ日時 2026-08-28 21:47:54
合計ジャッジ時間 7,827 ms
ジャッジサーバーID
(参考情報)
judge1_0 / judge3_0
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 2
other AC * 28
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#line 1 "main.cpp"
#include <bits/stdc++.h>
using namespace std;

#include <immintrin.h> 
#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 <typename T>
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 <typename T>
using Edges = vector<edge<T>>;
template <typename T>
using WeightedGraph = vector<Edges<T>>;
using UnweightedGraph = vector<vector<int>>;

// 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 <typename T>
WeightedGraph<T> wgraph(int N, int M = -1, bool is_directed = false,
                        bool is_1origin = true) {
  WeightedGraph<T> 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 <typename T>
Edges<T> esgraph([[maybe_unused]] int N, int M, int is_weighted = true,
                 bool is_1origin = true) {
  Edges<T> 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 <typename T>
vector<vector<T>> adjgraph(int N, int M, T INF, int is_weighted = true,
                           bool is_directed = false, bool is_1origin = true) {
  vector<vector<T>> d(N, vector<T>(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 <typename T>
vector<T> bellman_ford(int N, Edges<T> &es, int start = 0, int goal = -1) {
  T INF = numeric_limits<T>::max() / 2;
  vector<T> 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<T>();
  vector<bool> 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<T>();
  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 <typename Key, typename Val>
struct RadixHeap {
  using uint = typename make_unsigned<Key>::type;
  static constexpr int bit = sizeof(Key) * 8;
  array<vector<pair<uint, Val> >, bit + 1> vs;
  array<uint, bit + 1> 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<uint, Val> 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 <typename T, bool Cond = is_void<T>::value>
struct E;
template <typename T>
struct E<T, false> {
  int to;
  T cost;
  E() {}
  E(const int& v, const T& c) : to(v), cost(c) {}
  operator int() const { return to; }
};
template <typename T>
struct E<T, true> {
  int to;
  E() {}
  E(const int& v) : to(v) {}
  operator int() const { return to; }
};

template <typename T = void>
struct StaticGraph {
 private:
  template <typename It>
  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<int> head;
  vector<pair<int, E<T>>> buf;
  vector<E<T>> 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 <typename... Args>
  void add_edge(int u, Args&&... args) {
#pragma GCC diagnostic ignored "-Wnarrowing"
    buf.emplace_back(u, E<T>{std::forward<Args>(args)...});
#pragma GCC diagnostic warning "-Wnarrowing"
    ++head[u];
    if ((int)buf.size() == M) build();
  }

  Es<typename vector<E<T>>::iterator> operator[](int u) {
    return {begin(es) + head[u], begin(es) + head[u + 1]};
  }
  const Es<typename vector<E<T>>::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 <typename T>
vector<T> dijkstra(StaticGraph<T>& g, int start = 0) {
  vector<T> d(g.size(), T(-1));
  RadixHeap<T, int> 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 <typename T>
T dijkstra_point(StaticGraph<T>& g, int start, int goal) {
  vector<T> d(g.size(), T(-1));
  RadixHeap<T, int> 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 <typename T>
vector<pair<T, int>> dijkstra_restore(StaticGraph<T>& g, int start = 0) {
  vector<pair<T, int>> d(g.size(), {T(-1), -1});
  RadixHeap<T, int> 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<ll>::max() / 2;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int n, m; cin >> n >> m;
	vector<ll> p(n); for (auto& x : p) cin >> x;
	Edges<ll> es;
	vector<tuple<int, int, ll>> ori;
	ori.reserve(m);
	for (int i=0; i<m; i++) {
		int u, v; ll t; cin >> u >> v >> t; u--; v--;
		es.emplace_back(u, v, t);
		ori.emplace_back(u, v, t);
	}

	for (int i=0; i<n; i++) es.emplace_back(n, i, 0);
	auto h_all = bellman_ford<ll>(n+1, es, n);
	vector<ll> h(n);
	for (int i=0; i<n; i++) h[i] = h_all[i];
  	StaticGraph<ll> 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<n; s++) {
		auto d = dijkstra(g, s);
    	for (int t=0; t<n; t++) if (s != t) if (d[t] != -1){
			ll dist = d[t] - h[s] + h[t];
			ll cost = p[s] + dist + p[t];
			if (cost < ans) {
				ans = cost;
				cnt = 1;
			} else if (cost == ans) cnt++;
		}
  	}

	if (ans == inf) cout << -1 << '\n';
	else cout << ans << ' ' << cnt << '\n';
}
0