森森旅遊(天梯賽)
阿新 • • 發佈:2022-03-22
首先考慮最短路,從1跑dj用現金,從n跑dj用旅行金,動態修改
因為只要求最少的現金,用multiset維護
有一個坑點,題目說的是一個現金換ai個旅行金,那就是隻能換一個現金,不能再換多了
點選檢視程式碼
#include <bits/stdc++.h> using namespace std; const int N = 100010; using PII = pair<int, int>; using LL = long long; using PLI = pair<LL, int>; const LL INF = 1e18; vector<PII> G[N], rG[N]; int n, m, q, a[N]; LL dis[N], rdis[N], res[N]; bool st[N]; void dijkstra(int S, LL dis[], int op) { for(int i = 1; i <= n; ++ i) { dis[i] = INF; st[i] = false; } priority_queue<PLI, vector<PLI>, greater<PLI>> Q; Q.push({0, S}); dis[S] = 0; while(!Q.empty()) { int u = Q.top().second; Q.pop(); if(st[u]) continue; st[u] = true; if(op) { for(auto &[v, w] : G[u]) if(dis[v] > dis[u] + w) { dis[v] = dis[u] + w; Q.push({dis[v], v}); } } else { for(auto &[v, w] : rG[u]) { if(dis[v] > dis[u] + w) { dis[v] = dis[u] + w; Q.push({dis[v], v}); } } } } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); cin >> n >> m >> q; for(int i = 0; i < m; ++ i) { int u, v, c, d; cin >> u >> v >> c >> d; G[u].push_back({v, c}); rG[v].push_back({u, d}); } for(int i = 1; i <= n; ++ i) cin >> a[i]; dijkstra(1, dis, 1); dijkstra(n, rdis, 0); multiset<LL> S; for(int i = 1; i <= n; ++ i) { if(dis[i] == INF or rdis[i] == INF) continue; res[i] = dis[i] + (rdis[i] + a[i] - 1) / a[i]; S.insert(res[i]); } while(q -- ) { int x, v; cin >> x >> v; if(dis[x] != INF and rdis[x] != INF) { auto it = S.find(res[x]); S.erase(it); res[x] = dis[x] + (rdis[x] + v - 1) / v; S.insert(res[x]); } cout << *S.begin() << "\n"; } return 0; }