[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);
        }
    }
}
posted @ 2024-12-16 09:07  ~Cyan~  阅读(1)  评论(0编辑  收藏  举报