1. 程式人生 > >迪克斯特拉演算法詳解及C++實現

迪克斯特拉演算法詳解及C++實現

演算法步驟如下:
G={V,E}
1. 初始時令 S={V0},T=V-S={其餘頂點},T中頂點對應的距離值
若存在<V0,Vi>,d(V0,Vi)為<V0,Vi>弧上的權值
若不存在<V0,Vi>,d(V0,Vi)為∞
2. 從T中選取一個與S中頂點有關聯邊且權值最小的頂點W,加入到S中
3. 對其餘T中頂點的距離值進行修改:若加進W作中間頂點,從V0到Vi的距離值
4. 縮短,則修改此距離值
重複上述步驟2、3,直到S中包含所有頂點,即W=Vi為止
Dijkstra演算法適用於邊權為正的情況。下面直接給出Dijkstra演算法的虛擬碼,它
可用於計算正權圖上的單源最短路(Single-Source Shortest Paths,SSSP),
即從單個源點出發,到所有結點的最短路。該演算法同時適用於有向圖和無向圖。
清除所有點的標號
設d[0]=0,其他d[i]=INF
迴圈n次 {
在所有未標號結點中,選出d值最小的結點x
給結點x標記
對於從x出發的所有邊(x,y),更新d[y] = min{d[y], d[x]+w(x,y)}
}
下面是虛擬碼對應的程式。假設起點是結點0,它到結點i的路徑長度為d[i]。未標
號結點的v[i
]=0,已標號結點的v[i]=1。為了簡單起見,用w[x][y]==INF表示邊 (x,y)不存在。 memset(v, 0, sizeof(v)); for(int i = 0; i < n; i++) d[i] = (i==0 ? 0 : INF); for(int i = 0; i < n; i++) { int x, m = INF; for(int y = 0; y < n; y++) if(!v[y] && d[y]<=m) m = d[x=y]; v[x] = 1; for(int y = 0; y < n; y++) d[y] = min(d[y], d
[x] + w[x][y]); }
#include<iostream>
using namespace std;
#define inf 1000000
#define maxn 1010
#define maxm 50010
int v[maxn];
int d[maxn];
int w[maxn][maxn];
int n,m,s;
void dj(int s)
{
    for(int i=1;i<=n;i++)d[i]=(i==s?0:inf);
    for(int i=1;i<=n;i++){
        int x,m=inf;
        for(int y=1
;y<=n;y++)if(!v[y]&&d[y]<m)m=d[x=y]; v[x]=1; for(int y=1;y<=n;y++)d[y]=min(d[y],d[x]+w[x][y]); } for(int i=1;i<=n;i++) printf("%d ",d[i]); } int main() { //freopen("D:\\1.txt","r",stdin); cin>>n>>m>>s; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i!=j)w[i][j]=inf; for(int i=0;i<m;i++) { int u,v,wei; getchar(); scanf("%d%d%d",&u,&v,&wei); w[u][v]=wei; } dj(s); }