CF843D Dynamic Shortest Path 题解
思路
发现这个东西是一个动态的最短路问题。如果我们要去暴力做的话复杂度是 \(qn\log m\) 的。
发现 \(q\) 并不很大,同时时限相对大,因此考虑把 dij 的过程朝这个方向优化。
我们可以看出由于每次边权都只能加 1,因此我们考虑一个 trick:每次 dij 去求与原来最短路的权值的差值。这样可以通过扫值域的方式去掉堆得 \(\log m\)。
可以发现这个东西的复杂度上界是与每次最短路的权值变化上界挂钩的。又由于每条边只能 +1,因此单次计算的复杂度就是 \(O(n+m)\) 的,总复杂度为 \(O(n\log m-q(n+m))\)。
code
但是被卡飞了。注意需要用链式前向星,会快很多。但这里写的是用 vector 的代码。
#pragma GCC optimize ("Ofast")
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair <int,int>
#define mp make_pair
const int N=1e5+7,inf=1e18+7;
int n,m,qq,tot[N],d[N],f[N],vis[N];
pii id[N];
struct node{int v,w;};
vector <node> q[N];
priority_queue <pii> t;
inline void dij(){
for(int i=2;i<=n;i++)d[i]=inf;d[1]=0;t.push(mp(0,1));
while(!t.empty()){
int u=t.top().second;t.pop();if(vis[u])continue;vis[u]=1;
for(int i=0;i<tot[u];i++){
int v=q[u][i].v,w=q[u][i].w;
if(d[v]>d[u]+w) d[v]=d[u]+w,t.push(mp(-d[v],v));
}
}
}
queue <int> tt[N];
inline void bfs(int c){
int mx=0;
for(int i=2;i<=n;i++)f[i]=inf;f[1]=0;tt[0].push(1);
for(int i=0;i<=mx;i++){
while(!tt[i].empty()){
int u=tt[i].front();tt[i].pop();
if(f[u]<i)continue;
for(int i=0;i<tot[u];i++){
int v=q[u][i].v,w=d[u]-d[v]+q[u][i].w;
if(f[v]>f[u]+w){f[v]=f[u]+w;if(f[v]<=min(c,n-1))mx=max(mx,f[v]),tt[f[v]].push(v);}
}
}
}
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n>>m>>qq;
for(int i=1,u,v,w;i<=m;i++) cin>>u>>v>>w,q[u].push_back({v,w}),tot[u]++,id[i]=mp(u,tot[u]-1);
dij();
while(qq--){
int op,c;cin>>op>>c;
if(op==1){if(d[c]>=inf)cout<<"-1\n";else cout<<d[c]<<'\n';}
else{
for(int i=1,t;i<=c;i++) cin>>t,++q[id[t].first][id[t].second].w;
bfs(c);
for(int u=1;u<=n;u++) d[u]=min(inf,d[u]+f[u]);
}
}
}

浙公网安备 33010602011771号