最短路徑問題—Dijkstra演算法
阿新 • • 發佈:2021-01-13
最短路徑問題—Dijkstra演算法
Dijkstra演算法:
簡稱dij(弗洛伊德)演算法
-
用來計算從一個點到其他所有點的最短路徑的演算法,是一種單源最短路徑演算法。也就是說,只能計算起點只有一個的情況。
- 優點:時間複雜度是 O (N2),比Floyd快
- 缺點:它 不能處理存在負邊權的情況
演算法思路
從起點到一個點的最短路徑一定會經過至少一個“中轉點”(例如下圖1到5的最短路徑,中轉點是2。特殊地,我們認為起點1也是一個“中轉點”)
顯而易見,如果我們想求出起點到一個點的最短路徑,那我們必然要先求出中轉點的最短路徑
我們把點分為兩類,一類是已確定最短路徑的點,稱為“白點”,另一類是未確定最短路徑的點,稱為“藍點”。
如果我們要求出一個點的最短路徑,就是把這個點由藍點變為白點。從起點到藍點的最短路徑上的中轉點在這個時刻只能是白----點。
Dijkstra的演算法思想,就是一開始將起點到起點的距離標記為0,而後進行n次迴圈,每次找出一個到起點距離dis[u]最短的點u,
將它從藍點變為白點。隨後列舉所有的藍點vi,如果以此白點為中轉到達藍點vi的路徑dis[u]+w[u][vi]更短的話,
將它作為vi的“更短路徑”dis[vi](此時還不確定是不是vi的最短路徑)。
3 4
接下來的兩輪迴圈將4、5也變成白點。N輪迴圈結束後,所有的點的最短路徑即能求出。
題目程式碼
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int x[110],y[110],n,m,s,t,l,r,u,g;
bool b[110];
double a[110][110],mn[110];
void in()
{
cin>>n;
for (int i=1;i<=n;i++)
{
cin>>x[i]>>y[i];
}cin>>m;
memset(mn,0x7f7f7f7f,sizeof(mn));
for(int i=1;i<=m;i++)
{
cin>>l>>r;
a[l][r]=sqrt(abs(x[l]-x[r])*abs(x[l]-x[r])+abs(y[l]-y[r])*abs(y[l]-y[r]));
a[r][l]=sqrt(abs(x[l]-x[r])*abs(x[l]-x[r])+abs(y[l]-y[r])*abs(y[l]-y[r]));
}cin>>s>>t;
}
void Dijkstra()
{
mn[s]=0;
for(int i=1;i<=n;i++){
g=0x7f7f7f7f;
for(int j=1;j<=n;j++){
if(!b[j]&&g>mn[j]){
u=j;g=mn[j];
}
}b[u]=1;
for(int j=1;j<=n;j++){
if(!b[j]&&a[u][j]){
mn[j]=min(mn[j],mn[u]+a[u][j]);
}
}
}
}
int main()
{
in();
Dijkstra();
printf("%0.02lf",mn[t]);
}