首先考虑最短路,从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;
}