safety の値を2分探索しながらダイクストラする。
ところどころ signed int に収まらないことに注意。
問題文が長いし、どこか見落としそう。
UVaみたいな問題だから好きになれない。
struct E { int src, dst; lli F, T, P; }; const int N = 500; vector<E> g[N]; lli calc_next(E e, lli curr_time) { lli a = curr_time - e.F; if (a <= 0) return e.F + e.T; lli b = (a / e.P) + (bool)(a % e.P); lli c = b * e.P; return e.F + c + e.T; } bool sssp(int n, lli limit, lli safety) { priority_queue< pair<lli, lli> > q; static lli cost[N]; fill(cost, cost + N, (1LL << 60)); for (q.push(make_pair(0, 0)); q.size(); ) { lli curr = q.top().second; lli time = -q.top().first; q.pop(); each (e, g[curr]) { lli next = calc_next(*e, time + (curr ? safety : 1)); if (cost[e->dst] > next) { cost[e->dst] = next; q.push(make_pair(-next, e->dst)); } } } return cost[n - 1] <= limit; } class TheAirTripDivOne { public: int find(int n, vector <string> fs, int time) { fill(g, g + N, vector<E>()); string s = accumulate(fs.begin(), fs.end(), string("")); replace(s.begin(), s.end(), ',', ' '); istringstream iss(s); for (E e; iss >> e.src >> e.dst >> e.F >> e.T >> e.P; ) { --e.src; --e.dst; g[e.src].push_back(e); } lli small = 1, large = time + 1; while (small + 1 < large) { lli mid = (small + large) / 2; if (!sssp(n, time, mid)) large = mid; else small = mid; } return sssp(n, time, small) ? small : -1; } };