zoukankan      html  css  js  c++  java
  • CF843D Dynamic Shortest Path

    带权有向图,支持一下操作:

    1. 询问(1)到某个点(v)的最短路。
    2. 读入一个边集,将这些边的边权都加(1)

    (n,mle 10^5,Qle 2000)


    正解可以猜到是(O(mQ))级别的。

    如果最大距离为(W),可以用(O(w))大小的桶来优化dijkstra,做到(O(m+W))的时间。

    注意到每次边权的变化量都很小,于是(Delta wle n-1)

    用改边权的套路来把(W)缩小:先跑一边普通的最短路求出(dis_i),然后将边((u,v,w))(w)改成(dis_u+w-dis_v)。由三角形不等式得修改后边权仍然非负。

    现在对边权进行修改,然后再跑最短路,这时候跑出来的(dis'_i)表示(dis_i)的增加量。

    由于一定有(dis_i'le n-1),所以每次时间是(O(m+n))

    跑完之后继续更新边权即可。


    using namespace std;
    #include <bits/stdc++.h>
    #define N 100005
    #define ll long long
    #define mp(x,y) make_pair(x,y)
    #define fi first
    #define se second
    #define INF 100000000000000
    int n,m;
    struct EDGE{
    	int to,w;
    	EDGE *las;
    } e[N];
    int ne;
    EDGE *last[N];
    void link(int u,int v,int w){
    	e[ne]={v,w,last[u]};
    	last[u]=e+ne++;
    }
    ll dis[N],f[N];
    void adjust(){
    	for (int i=1;i<=n;++i)
    		for (EDGE *ei=last[i];ei;ei=ei->las)
    			ei->w+=dis[i]-dis[ei->to];
    	for (int i=1;i<=n;++i)
    		f[i]+=dis[i];
    }
    void SP0(){
    	typedef pair<ll,int> info;
    	static priority_queue<info,vector<info>,greater<info> > q;
    	memset(dis,127,sizeof(ll)*(n+1));
    	dis[1]=0;
    	q.push(mp(0,1));
    	while (!q.empty()){
    		int x=q.top().se;
    		ll s=q.top().fi;
    		q.pop();
    		if (s!=dis[x])
    			continue;
    		for (EDGE *ei=last[x];ei;ei=ei->las)
    			if (s+ei->w<dis[ei->to]){
    				dis[ei->to]=s+ei->w;
    				q.push(mp(dis[ei->to],ei->to));
    			}
    	}
    	adjust();
    }
    void SP1(){
    	static vector<int> b[N];
    	memset(dis,127,sizeof(ll)*(n+1));
    	dis[1]=0;
    	b[0].push_back(1);
    	for (int i=0;i<n;++i){
    		for (int j=0;j<b[i].size();++j){
    			int x=b[i][j];
    			if (dis[x]<i)
    				continue;
    			for (EDGE *ei=last[x];ei;ei=ei->las)
    				if (i+ei->w<n && i+ei->w<dis[ei->to]){
    					dis[ei->to]=i+ei->w;
    					b[dis[ei->to]].push_back(ei->to);
    				}
    		}
    		b[i].clear();
    	}
    	adjust();
    }
    int main(){
    //	freopen("in.txt","r",stdin);
    	int Q;
    	scanf("%d%d%d",&n,&m,&Q);
    	for (int i=0;i<m;++i){
    		int u,v,w;
    		scanf("%d%d%d",&u,&v,&w);
    		link(u,v,w);
    	}
    	SP0();
    	while (Q--){
    		int op;
    		scanf("%d",&op);
    		if (op==1){
    			int v;
    			scanf("%d",&v);
    			printf("%lld
    ",dis[v]>INF?-1:f[v]);
    		}
    		else{
    			int c;
    			scanf("%d",&c);
    			for (int i=0;i<c;++i){
    				int id;
    				scanf("%d",&id),--id;
    				e[id].w++;
    			}
    			SP1();
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Codeforces Round #366 (Div. 2)
    Codeforces Round #367 (Div. 2)
    带权并查集小练
    Codeforces Round #368 (Div. 2)
    Codeforces Round #396 (Div. 2)
    Codeforces Round #376 (Div. 2)
    工作流
    程序员之江湖感想
    工作流设计简介
    程序员常去的103个网站
  • 原文地址:https://www.cnblogs.com/jz-597/p/14433406.html
Copyright © 2011-2022 走看看