結果
問題 |
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; }