結果
| 問題 |
No.3111 Toll Optimization
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2025-04-19 09:39:56 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 211 ms / 5,000 ms |
| コード長 | 5,860 bytes |
| コンパイル時間 | 4,154 ms |
| コンパイル使用メモリ | 291,580 KB |
| 実行使用メモリ | 50,516 KB |
| 最終ジャッジ日時 | 2025-04-19 09:40:10 |
| 合計ジャッジ時間 | 12,403 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 70 |
ソースコード
#include <bits/stdc++.h>
#define rep(i, n) for(int i=0, i##_len=(n); i<i##_len; ++i)
#define reps(i, n) for(int i=1, i##_len=(n); i<=i##_len; ++i)
#define rrep(i, n) for(int i=((int)(n)-1); i>=0; --i)
#define rreps(i, n) for(int i=((int)(n)); i>0; --i)
#define all(v) (v).begin(), (v).end()
#define el '\n'
using namespace std;
using ll = long long;
using ull = unsigned long long;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using vvvi = vector<vector<vector<int>>>;
using vl = vector<ll>;
using vvl = vector<vector<ll>>;
using vvvl = vector<vector<vector<ll>>>;
using vs = vector<string>;
using pi = pair<int, int>;
using pl = pair<ll, ll>;
template<class T> using min_priority_queue = priority_queue<T, vector<T>, greater<T>>;
template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
template<class T> bool chmaxeq(T &a, const T &b) { if (a<=b) { a=b; return 1; } return 0; }
template<class T> bool chmineq(T &a, const T &b) { if (b<=a) { a=b; return 1; } return 0; }
bool yes(bool a=true) { cout << (a?"yes":"no") << el; return a; }
bool no(bool a=true) { cout << (a?"no":"yes") << el; return a; }
bool Yes(bool a=true) { cout << (a?"Yes":"No") << el; return a; }
bool No(bool a=true) { cout << (a?"No":"Yes") << el; return a; }
bool YES(bool a=true) { cout << (a?"YES":"NO") << el; return a; }
bool NO(bool a=true) { cout << (a?"NO":"YES") << el; return a; }
template<class T1, class T2> istream &operator>>(istream &is, pair<T1, T2> &p);
template<class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &p);
template<class T> istream &operator>>(istream &is, vector<T> &v);
template<class T> ostream &operator<<(ostream &os, const vector<T> &v);
template<class T1, class T2>
istream &operator>>(istream &is, pair<T1, T2> &p) {
return is >> p.first >> p.second;
}
template<class T1, class T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
return os << p.first << ' ' << p.second;
}
template<class T>
istream &operator>>(istream &is, vector<T> &v) {
int sz = v.size();
for (int i = 0; i < sz; i++) is >> v[i];
return is;
}
template<class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
int sz = v.size();
for (int i = 0; i < sz; i++) {
if (i) os << ' ';
os << v[i];
}
return os;
}
void _main();
int main() { cin.tie(0); ios::sync_with_stdio(0); cout << fixed << setprecision(16); _main(); return 0; }
/**
* @brief Dijkstra 法によって単一始点最短経路を求めるクラス。
*
* @tparam T 辺の重みを表す整数型
*/
template<class T>
struct dijkstra {
static const T INF;
/**
* @brief `n` 頂点 0 辺のグラフで初期化する。
*
* @param n 頂点数
*/
dijkstra(int n) : _g(n) {}
/**
* @brief `from` から `to` へ重さ `cost` の有向辺を追加する。
*
* @param from 始点
* @param to 終点
* @param cost 重み
*/
void add_edge(int from, int to, T cost) {
_g[from].push_back(edge(to, cost));
}
/**
* @brief `from` から `to` へ重さ `cost` の無向辺を追加する。
*
* @param from 始点
* @param to 終点
* @param cost 重み
*/
void add_indirected_edge(int from, int to, T cost) {
add_edge(from, to, cost);
add_edge(to, from, cost);
}
/**
* @brief `s` を始点として各頂点への最短経路長を求める。
*
* O(V+E log E)
* @param s 始点
* @return 各頂点への最短経路長
*/
vector<T> calc(int s) {
vector<T> d(_g.size(), INF);
_prev = vector<int>(_g.size(), -1);
d[s] = 0;
priority_queue<pair<T, int>, vector<pair<T, int>>, greater<pair<T, int>>> q;
q.push({0, s});
while (!q.empty()) {
pair<T, int> p = q.top();
q.pop();
int v = p.second;
if (d[v] < p.first) continue;
for (auto &e : _g[v]) {
if (d[e.to] > d[v]+e.cost) {
d[e.to] = d[v]+e.cost;
_prev[e.to] = v;
q.push({d[e.to], e.to});
}
}
}
return d;
}
/**
* @brief `s` から `t` への最短経路長を求める。
*
* O(V+E log E)
* @param s 始点
* @param t 終点
* @return `s` から `t` への最短経路長
*/
T calc(int s, int t) {
vector<T> d(_g.size(), INF);
_prev = vector<int>(_g.size(), -1);
d[s] = 0;
priority_queue<pair<T, int>, vector<pair<T, int>>, greater<pair<T, int>>> q;
q.push({0, s});
while (!q.empty()) {
pair<T, int> p = q.top();
q.pop();
int v = p.second;
if (v == t) return d[v];
if (d[v] < p.first) continue;
for (auto &e : _g[v]) {
if (d[e.to] > d[v]+e.cost) {
d[e.to] = d[v]+e.cost;
_prev[e.to] = v;
q.push({d[e.to], e.to});
}
}
}
return INF;
}
/**
* @brief `t` への最短パスを 1 つ求め、通る頂点を順に並べた `vector` を返す。事前に `calc(s)` を呼び出しておく必要がある。
*
* @param t 終点
* @return `t` への最短パスで通る頂点を順に並べた `vector`
*/
vector<int> get_path(int t) {
vector<int> path;
for (int cur = t; cur != -1; cur = _prev[cur]) {
path.push_back(cur);
}
reverse(path.begin(), path.end());
return path;
}
private:
struct edge {
int to;
T cost;
edge(int to, T cost) : to(to), cost(cost) {}
};
vector<vector<edge>> _g;
vector<int> _prev;
};
template<> const int dijkstra<int>::INF = 1001001001;
template<> const long long dijkstra<long long>::INF = 1LL << 60;
void _main() {
ll N, M, K; cin >> N >> M >> K;
dijkstra<ll> g(N*(K+1)+1);
vl C(M); cin >> C;
rep(i, M) {
ll u, v; cin >> u >> v;
u--; v--;
rep(j, K+1) g.add_indirected_edge(u+N*j, v+N*j, C[i]);
rep(j, K) {
g.add_edge(u+N*j, v+N*(j+1), 0);
g.add_edge(v+N*j, u+N*(j+1), 0);
}
}
rep(i, K+1) g.add_indirected_edge(N-1+N*i, N*(K+1), 0);
ll ans = g.calc(0, N*(K+1));
cout << (ans==dijkstra<ll>::INF?-1:ans) << el;
}