Dijkstra 算法次短路經的若干應用

1) 求可重複頂點的次短路徑
基本方法從起點 s 出發求一次最短路,用 ds[] 記錄最短路徑長度,從終點 t 對反向圖求一次最短路徑,dt[]記錄最短距離,然後枚舉每一條邊 <u,v>,取 ds+ w(u,v)+ dt[v] 最小而又大於最短路徑的就是次短路徑。
pku 3255  Roadblocks
代碼:
#include <iostream>
#include <cstdio>
#include <queue>
#include <functional>
#include <algorithm>
#include <vector>

using namespace std;

typedef pair<int,int> PAIR;
int const N= 5010, inf= 0x7fffffff;
vector<PAIR> g[N];
int ds[N], dt[N], n, r;

void Dijkstra( int S, int dist[] ){
    priority_queue<PAIR, vector<PAIR>, greater<PAIR> > que;
    for( int i= 0; i<= n; ++i )dist= inf;
    
    que.push( PAIR(0,S) ); dist[S]= 0;
    while( !que.empty() ){
        int len= que.top().first, u= que.top().second; que.pop();
        if( len> dist ) continue;
        
        for( int i= 0; i< g.size(); ++i ){
            int v= g.first, w= g.second;
            if( len+ w< dist[v] ){
                dist[v]= len+ w;
                que.push( PAIR( dist[v], v ) );
            }
        }
    }
}

int main(){
    while( scanf("%d%d",&n,&r)!= EOF ){
        for( int i= 0; i< r; ++i ){
            int u, v, d;
            scanf("%d%d%d", &u,&v,&d );
            g.push_back( PAIR(v,d) );
            g[v].push_back( PAIR(u,d) );
        }
        Dijkstra( 1, ds );
        int sd= ds[n];
        Dijkstra( n, dt );
        
        int ans= inf;
        for( int u= 1; u<= n; ++u )
        for( size_t i= 0; i< g.size(); ++i ){
            int v= g.first, w= g.second;
            
            if( ds+ w+ dt[v]!= sd && ds+ w+ dt[v]< ans )
            ans= ds+ w+ dt[v];
        }
        printf("%d\n", ans );
        for( int i= 0; i<= n; ++i ) g.clear();
    }
    
    return 0;
}
2) 求不可重複頂點的次短路徑
一種方法就是刪邊,再求最短路徑,複雜度有些高,沒想到很好的方法。

3) 求最短路徑的條數
基本方法爲採用遞推,用 p[] 記錄路徑條數,如果 dist+ w(u,v)== dist[v] ,則 p[v]+= p,如果
dist+ w(u,v)< dist[v] 則 p[v]= p。
UESTC 1053 Shortest road 

代碼:

#include <iostream>
#include <vector>
#include <cstdio>
#include <queue>
#include <functional>

using namespace std;

typedef pair<int,int> PAIR;
int const N= 1010, inf= 0x7fffffff;
vector<PAIR> mat[N];
int dist[N], path[N], mod= 1000007, m, n, S, T;

int Dijkstra(){
    priority_queue<PAIR,vector<PAIR>,greater<PAIR> > que;
    for( int i= 0; i<= n; ++i ) { dist= inf; path= 0; }
    dist[S]= 0; path[S]= 1; que.push( PAIR(0,S) );
    
    while( !que.empty() ){
        int len= que.top().first, u= que.top().second; que.pop();
        
        if( len!= dist ) continue;
        for( size_t i= 0; i< mat.size(); ++i ){
            int v= mat.first, w= mat.second;
            
            if( len+ w< dist[v] ){
                dist[v]= len+ w; path[v]= path;
                que.push( PAIR( dist[v], v ) );
            }
            else if( len+ w== dist[v] ) path[v]= ( path[v]+ path )% mod;
        }
    }
    return dist[T];
}

int main(){
    int test;
    scanf("%d",&test );
    while( test-- ){
        scanf("%d%d",&n,&m);
        for( int i= 0; i< m; ++i ){
            int u, v, d;
            scanf("%d%d%d", &u,&v,&d );
            mat.push_back( PAIR(v,d) );
            mat[v].push_back( PAIR(u,d) );
        }
        scanf("%d%d",&S,&T );
        int sd= Dijkstra();
        
        if( sd== inf ) puts("0\n0");
        else{
            printf("%d\n%d\n", sd, path[T] );
        }
        puts("");
        for( int i= 0; i<= n; ++i ) mat.clear();
    }
    
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章