[CF843D] Dynamic Shortest Path
考虑暴力,显然就是 \(O(qm\log{m})\),暴力做 \(q\) 次最短路即可。
但这显然不可过。注意到每次只会对 \(c\) 条边的边权 \(+1\),也就是说每一次修改 \(dis_x\) 最多增加 \(c\),所以在权值上模拟最短路的操作即可,具体就是从距离为 \(0\) 开始,对于原来的边 \((u,v,w)\) ,改变成 \((u,v,dis_u - dis_v + w)\),表示通过这条路,\(dis_v\) 会增加多少。
然后就做完了,复杂度 \(O(q(n+m) + \sum c)\)
点击查看代码
#include<bits/stdc++.h>
#define fir first
#define sec second
#define lowbit(x) x&(-x)
#define mkp(a,b) make_pair(a,b)
using namespace std;
typedef pair<int,int> pir;
inline int read(){
int x=0,f=1; char c=getchar();
while(!isdigit(c)){if(c=='-') f=-1; c=getchar();}
while(isdigit(c)){x=x*10+(c^48); c=getchar();}
return x*f;
}
const int N=1e5+5;
const long long inf=1e15;
int n,m,q;
long long dis[N];
int vis[N];
struct edge{int v,nxt,w;}p[N];
int head[N],cnt;
inline void add(int u,int v,int w){
p[++cnt]={v,head[u],w};
head[u]=cnt;
}
struct node{
int x; long long dis;
bool operator<(const node& a)const{return a.dis<dis;}
};
inline void dij(int s){
priority_queue<node> qu;
for(int i=1;i<=n;i++) dis[i]=inf,vis[i]=0;
dis[s]=0;
qu.push(node{s,0});
while(!qu.empty()){
auto [x,d]=qu.top();
qu.pop();
if(vis[x]) continue;
vis[x]=1;
for(int i=head[x];i;i=p[i].nxt){
int v=p[i].v,w=p[i].w;
if(dis[v]>dis[x]+w){
dis[v]=dis[x]+w;
qu.push(node{v,dis[v]});
}
}
}
}
int D[N];
queue<int> qu[N];
inline void bfs(int c){
for(int i=1;i<=n;i++) D[i]=n+1;
D[1]=0;
int now=0;
qu[now].push(1);
for(int i=0;i<=now;i++){
while(!qu[i].empty()){
int x=qu[i].front();
qu[i].pop();
if(D[x]<i) continue;
for(int j=head[x];j;j=p[j].nxt){
int v=p[j].v,w=p[j].w+dis[x]-dis[v];
if(D[x]>min(c,n-1)-w) continue;
if(D[v]>D[x]+w){
D[v]=D[x]+w;
if(D[v]<=min(c,n-1))
qu[D[v]].push(v),now=max(now,D[v]);
}
}
}
}
// for(int i=1;i<=n;i++) cout<<D[i]<<' ';
// puts("\n--------------");
for(int i=1;i<=n;i++) dis[i]=min(inf,D[i]+dis[i]);
}
signed main(){
n=read(),m=read(),q=read();
for(int i=1;i<=m;i++){
int u=read(),v=read(),w=read();
add(u,v,w);
}
dij(1);
while(q--){
int opt=read();
if(opt==1){
int x=read();
if(dis[x]==inf) puts("-1");
else cout<<dis[x]<<'\n';
}
else{
int c=read();
for(int i=1;i<=c;i++){
int x=read();
p[x].w++;
}
bfs(c);
}
}
}