https://yukicoder.me/problems/no/848
前提知識
解説
https://yukicoder.me/submissions/357498
星2.5にしては、かなり難しい問題に見える。
こういう場合は、制約からエスパーするに限るのだが、N≦2000というのが弱点っぽい。
N^2っぽいので、DPをまず疑ったが、今までかかった時間と、一緒にいた時間を含めることができないので、これではなさそう。
さて、どうするという感じだが、よくあるのが実は最適戦略があるってパターンなので、こっちで攻めてみる。
なんとなく、途中まで一緒に行って、別れて、それぞれ観光名所に行って、合流して戻ってくれば良さそう。
観光名所に行く前に、別れて合流するパターンがあれば、別れた2つの道のうち距離が短い方で一緒に行けば最適化できる。
それっぽい理由もついたし、最初に分かれる所と、最後に合流する所を全探索すると、N^2で計算量もピッタリなので、方針あってそう。
祈って出すとACできる。
実装するときには、頂点1, 頂点P, 頂点Qから他への頂点への最短距離が必要になる。
これはダイクストラで各頂点を始点として、計算すればいい。
それぞれ、配列s, 配列p, 配列qとする。
最初に分かれるポイントを頂点a, 最後に合流するポイントを頂点bとする。
すると、全体でかかる時間は、s[a] + max(p[a] + p[b], q[a] + q[b]) + s[b]となる。これがT以下であれば、この行動は実現できる。
このときに一緒にいられない時間はmax(p[a] + p[b], q[a] + q[b])なので、一緒にいられる時間はT - max(p[a] + p[b], q[a] + q[b])となる。
これの最大値が答え。
int N, M, P, Q, T; //--------------------------------------------------------------------------------------------------- void _main() { cin >> N >> M >> P >> Q >> T; P--; Q--; vector<vector<pair<int, int>>> E(N); rep(i, 0, M) { int a, b, c; cin >> a >> b >> c; a--; b--; E[a].push_back({ b, c }); E[b].push_back({ a, c }); } vector<ll> s(N), p(N), q(N); dijk(0, E, s); dijk(P, E, p); dijk(Q, E, q); if (s[P] + p[Q] + q[0] <= T) { cout << T << endl; return; } ll ans = -1; rep(a, 0, N) rep(b, 0, N) { ll tot = s[a] + max(p[a] + p[b], q[a] + q[b]) + s[b]; if (tot <= T) { chmax(ans, T - (tot - s[a] - s[b])); } } cout << ans << endl; }