結果
| 問題 | No.3653 Space-Time Courier |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-07-20 00:05:34 |
| 言語 | C++23(gcc16) (gcc 16.1.0 + boost 1.90.0) |
| 結果 |
AC
|
| 実行時間 | 562 ms / 4,000 ms |
| + 54µs | |
| コード長 | 3,272 bytes |
| 記録 | |
| コンパイル時間 | 3,397 ms |
| コンパイル使用メモリ | 205,572 KB |
| 実行使用メモリ | 6,272 KB |
| 最終ジャッジ日時 | 2026-08-28 20:52:18 |
| 合計ジャッジ時間 | 9,590 ms |
|
ジャッジサーバーID (参考情報) |
judge1_0 / judge3_0 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 28 |
ソースコード
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
// 十分に大きな値を無限大(INF)として定義
const long long INF = 1e18;
// 隣接リスト用の辺構造体
struct Edge {
int to;
long long weight;
};
// 入力データ保持用の辺構造体
struct InputEdge {
int u, v;
long long t;
};
int main() {
// 標準入出力の高速化
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int N, M;
if (!(cin >> N >> M)) return 0;
// 基本コスト P の読み込み (1-indexed)
vector<long long> P(N + 1);
for (int i = 1; i <= N; ++i) {
cin >> P[i];
}
// 辺の読み込み
vector<InputEdge> input_edges(M);
for (int i = 0; i < M; ++i) {
cin >> input_edges[i].u >> input_edges[i].v >> input_edges[i].t;
}
// 1. Bellman-Ford法によるポテンシャル h の計算
// 全ての頂点に仮想頂点から重み0の辺があるものとし、初期値0で更新を行う
vector<long long> h(N + 1, 0);
for (int i = 0; i < N; ++i) {
bool updated = false;
for (const auto& edge : input_edges) {
if (h[edge.v] > h[edge.u] + edge.t) {
h[edge.v] = h[edge.u] + edge.t;
updated = true;
}
}
if (!updated) break; // 更新がなくなったら早期終了
}
// 2. 辺の重みの書き換え (非負化) と隣接リストの構築
vector<vector<Edge>> adj(N + 1);
for (const auto& edge : input_edges) {
long long w_prime = edge.t + h[edge.u] - h[edge.v];
adj[edge.u].push_back({edge.v, w_prime});
}
// 3. 各頂点からのDijkstra法
long long min_cost = INF;
long long min_count = 0;
for (int A = 1; A <= N; ++A) {
vector<long long> dist(N + 1, INF);
// 最小ヒープを構築 (pair<距離, 頂点番号>)
priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;
dist[A] = 0;
pq.push({0, A});
while (!pq.empty()) {
auto [d_u, u] = pq.top();
pq.pop();
if (d_u > dist[u]) continue;
for (const auto& edge : adj[u]) {
int v = edge.to;
long long w_prime = edge.weight;
if (dist[v] > d_u + w_prime) {
dist[v] = d_u + w_prime;
pq.push({dist[v], v});
}
}
}
// 始点 A から到達できた各頂点 B (A != B) に対してコストを計算・集計
long long const_A = P[A] - h[A];
for (int B = 1; B <= N; ++B) {
if (A == B || dist[B] == INF) continue;
// 変形したコスト式から元のコストを復元
long long cost = dist[B] + const_A + P[B] + h[B];
if (cost < min_cost) {
min_cost = cost;
min_count = 1;
} else if (cost == min_cost) {
min_count++;
}
}
}
// 出力処理
if (min_cost == INF) {
cout << -1 << "\n";
} else {
cout << min_cost << " " << min_count << "\n";
}
return 0;
}