結果
| 問題 | No.3653 Space-Time Courier |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-07-21 22:42:02 |
| 言語 | C++23(gcc16) (gcc 16.1.0 + boost 1.90.0) |
| 結果 |
AC
|
| 実行時間 | 567 ms / 4,000 ms |
| + 116µs | |
| コード長 | 3,034 bytes |
| 記録 | |
| コンパイル時間 | 1,452 ms |
| コンパイル使用メモリ | 208,108 KB |
| 実行使用メモリ | 6,272 KB |
| 最終ジャッジ日時 | 2026-08-28 21:02:39 |
| 合計ジャッジ時間 | 7,259 ms |
|
ジャッジサーバーID (参考情報) |
judge3_0 / judge2_0 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 28 |
ソースコード
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
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;
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;
}
// 仮想頂点 0 から全頂点 1..N への重み 0 の辺を考慮した Bellman-Ford
vector<long long> h(N + 1, INF);
h[0] = 0; // 仮想頂点 0 の距離を 0 とする
// input_edges に (0 -> i, 0) の辺を仮想的に含めて N 回更新
vector<InputEdge> bf_edges = input_edges;
for (int i = 1; i <= N; ++i) {
bf_edges.push_back({0, i, 0});
}
for (int i = 0; i <= N; ++i) {
bool updated = false;
for (const auto& edge : bf_edges) {
if (h[edge.u] != INF && h[edge.v] > h[edge.u] + edge.t) {
h[edge.v] = h[edge.u] + edge.t;
updated = true;
}
}
if (!updated) break;
}
// 辺の重みを非負化して隣接リストを構築
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});
}
long long min_cost = INF;
long long min_count = 0;
// 各頂点からの Dijkstra 法
for (int A = 1; A <= N; ++A) {
vector<long long> dist(N + 1, INF);
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});
}
}
}
// コストの復元と最小値の集計
for (int B = 1; B <= N; ++B) {
if (A == B || dist[B] == INF) continue;
// 元の最短距離: real_dist = dist[B] - h[A] + h[B]
long long real_dist = dist[B] - h[A] + h[B];
long long cost = real_dist + P[A] + P[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;
}