基本方法從起點 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;
}