ARC025 C - ウサギとカメ
解法
制約をみて,なんとなく全頂点を始点としてダイクストラできるなーと検討はつく.
とりあえず,目的地を決め打ちしてしまって,目的地を始点にダイクストラする.
その後,得られた距離 d[i] をソートしておく.
次に,カメのスタート地点を決め打ちして,中継地点からの距離を D とする.
すると,ウサギは D / T < d[i] / R を満たすような d,つまり D * R / T < d[i] を満たすような中継点からスタートすれば良いことがわかる.
このような i の個数は,ソートしておいた距離の候補上で二分探索すれば求めることができる.
ただし,ウサギがカメより遅い場合は,同じスタート地点からスタートしないように -1 しておく必要がある.
計算量は O((N+M)NlogN).
ソースコード
#include <bits/stdc++.h> using namespace std; using ll = long long; using weight = double; constexpr weight INF = 1e9; struct edge { int from, to; weight cost; bool operator<(edge const& rhs) const { return cost > rhs.cost; } }; using edges = std::vector<edge>; using graph = std::vector<edges>; void add_edge(graph& g, int from, int to, weight cost) { g[from].push_back(edge{from, to, cost}); } std::vector<weight> dijkstra(graph& g, int s) { using P = std::pair<weight, int>; std::vector<weight> d(g.size(), INF); std::priority_queue<P, std::vector<P>, std::greater<P>> que; fill(d.begin(), d.end(), INF); d[s] = 0; que.push(P{0, s}); while(!que.empty()) { P p = que.top(); que.pop(); int v = p.second; if(d[v] < p.first) { continue; } for(int i=0; i<g[v].size(); ++i) { edge e = g[v][i]; if(d[e.to] > d[v] + e.cost) { d[e.to] = d[v] + e.cost; que.push(P{d[e.to], e.to}); } } } return d; } int main() { int N, M; double R, T; cin >> N >> M >> R >> T; graph g(N); for(int i = 0; i < M; ++i) { int a, b, c; cin >> a >> b >> c; a--; b--; add_edge(g, a, b, c); add_edge(g, b, a, c); } ll res = 0; for(int i = 0; i < N; ++i) { auto d = dijkstra(g, i); sort(d.begin(), d.end()); for(int j = 1; j < N; ++j) { auto t = upper_bound(d.begin(), d.end(), d[j] * R / T) - d.begin(); res += N - t - (t <= j); } } cout << res << endl; }
感想
ウサギよりカメが早いケース,WA生やさずに気づけたけど完全に罠.
まあカメって走ると意外と早いからね.