zoukankan      html  css  js  c++  java
  • 分层图最短路[学习笔记]

    分层图最短路,主要是用来求解允许少量次数修改边权的最短路问题,由于修改此数较小,所以解法也有些许暴力.下面,让我们来看这么一道例题:

    description:

    有一(n)(m)边构成的连通图,给定起点(S)和终点(T),现允许你将至多(k(kleq10))条边的边权修改为(0),请你求出修改次数不超过(k)的情况下,(S)(T)的最短路径长度.

    solution:

    此题是分层图最短路模板题.首先不难想到一一枚举(k)条免费边,然后跑最短路,但算法复杂度(O((m+n)logn cdot C_{m}^{k})),极度暴力,连最小数据范围都十分吃力,于是我们便需引入新的思路.

    由于(k)较小,我们不妨构造(k+1)个相同的联通图,其中第(i)(i+1)个连通图中对应的边我们连上权值为(0)的单向边,以表示免费的边.用此方式,每次只能跑向层数更高的图,或在本层图内跑.且每跑进一个新图,意味着我们跑过了一条免费边,所以构造该分层图可以完美求解本题.答案即为每层终点的最短路的最小值,为方便起见,我们可以在每层终点向下一层终点连一条权值为(0)的单向边以传递最短路,最后输出最后一层终点的答案即可.

    code:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<map>
    #define R register
    #define next kdjadskfj
    #define debug puts("mlg")
    #define mod 1004535809
    #define Mod(x) ((x%mod+mod)%mod)
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    inline ll read();
    inline void write(ll x);
    inline void writeln(ll x);
    inline void writesp(ll x);
    ll n,m,k;
    ll head[3000000],next[3000000],to[3000000],w[3000000],tot;
    ll S,T;
    ll d[3000000];
    bool vis[3000000];
    
    inline void add(ll x,ll y,ll z){to[++tot]=y;next[tot]=head[x];head[x]=tot;w[tot]=z;}
    
    //queue<ll>q;
    //inline void spfa(){
    //	memset(d,0x3f,sizeof d);
    //	q.push(S);d[S]=0;
    //	while(q.size()){
    //		ll x=q.front();q.pop();vis[x]=false;
    //		for(R ll i=head[x],ver;i;i=next[i]){
    //			ver=to[i];
    //			if(d[ver]>d[x]+w[i]){
    //				d[ver]=d[x]+w[i];
    //				if(!vis[ver]){
    //					vis[ver]=true;
    //					q.push(ver);
    //				}
    //			}
    //		}
    //	}
    //}
    
    ll ans;
    priority_queue<pair<ll,ll> >q;
    inline void dijkstra(){
    	memset(d,0x3f,sizeof d);
    	d[S]=0;;
    	q.push(make_pair(0,S));
    	while(q.size()){
    		ll x=q.top().second;q.pop();
    		if(vis[x]) continue;
    		vis[x]=true;
    		for(R ll i=head[x],ver;i;i=next[i]){
    			ver=to[i];
    			if(d[ver]>d[x]+w[i]){
    				d[ver]=d[x]+w[i];
    				q.push(make_pair(-d[ver],ver));
    			}
    		}
    	}
    }
    
    int main(){	
    	n=read();m=read();k=read();
    	S=read()+1;T=read()+1;
    	while(m--){
    		ll x=read()+1,y=read()+1,z=read();
    		add(x,y,z);add(y,x,z);
    		for(R ll i=1;i<=k;i++){
    			add(x+i*n,y+i*n,z);add(y+i*n,x+i*n,z);
    			add(x+(i-1)*n,(y+i*n),0);
    			add(y+(i-1)*n,(x+i*n),0);
    		}
    	}
    	for(R ll i=1;i<=k;i++){
    		add(T+(i-1)*n,T+i*n,0);
    	}
    //	spfa();
    	dijkstra();
    	writeln(d[T+n*k]);
    }
    
  • 相关阅读:
    elasticsearch + python
    Django中的监控组件Prometheus
    MySQL索引原理以及最左前缀原则
    Insert ignore,还是insert replace还是insert on duplicate key update区别
    PyTorch中Tensor与numpy数据之间时共享的条件:
    在Numpy中numpy.nan显示成-9223372036854775808的缘故
    mac上安装pil报错: ERROR: Could not find a version that satisfies the requirement pil (from versions: none):
    OSError: [Errno 48] Address already in use
    curl: (7) Failed to connect to raw.githubusercontent.com port 443: Connection refused
    在实际项目中使用git推代码踩过的坑
  • 原文地址:https://www.cnblogs.com/ylwtsq/p/13409920.html
Copyright © 2011-2022 走看看