最近一直在刷題,遇到圖的問題就感覺無力迴天,所以我就總結一下,我對Dijkstra算法的理解
Dijkstra 的整體思路
圖解分析:
Dijkstra 的整體思路比較清晰
即進行n(n爲n的個數)次迭代去確定每個點到起點的最小值 最後輸出的終點的即爲我們要找的最短路的距離
所以按照這個思路除了存儲圖外我們還需要存儲兩個量
dist[n] //用於存儲每個點到起點的最短距離
st[n] //用於在更新最短距離時 判斷當前的點的最短距離是否確定 是否需要更新
每次迭代的過程中我們都先找到當前未確定的最短距離的點中距離最短的點
就像環形dp一樣,至於爲什麼是這樣那麼這就涉及到Dijkstra算法的具體數學證明了
int t=-1; //將t設置爲-1 因爲Dijkstra算法適用於不存在負權邊的圖
for(int j=1;j<=n;j++)
{
if(!st[j]&&(t==-1||dist[t]>dist[j]) //該步驟即尋找還未確定最短路的點中路徑最短的點
t=j;
}
通過上述操作當前我們的t代表就是剩餘未確定最短路的點中 路徑最短的點
而與此同時該點的最短路徑也已經確定我們將該點標記
st[t]=true;
然後用這個去更新其餘未確定點的最短距離
for(int j=1;j<=n;j++)
dist[j]=min(dist[j],dist[t]+g[t][j]);
//這裏可能有同學要問j如果從1開始的話 會不會影響之前已經確定的點的最小距離
//但其實是不會 因爲按照我們的Dijkstra算法的操作順序 先確定最短距離的點的距離已經比後確定的要小 所以不會影響
//這裏j從1開始只是爲了代碼的簡潔
進行n次迭代後最後就可以確定每個點的最短距離
然後再根據題意輸出相應的 要求的最短距離
以下爲完整代碼
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=10001;
int g[N][N]; //爲稠密陣所以用鄰接矩陣存儲
int dist[N]; //用於記錄每一個點距離第一個點的距離
bool st[N]; //用於記錄該點的最短距離是否已經確定
int n,m;
int Dijkstra()
{
memset(dist, 0x3f,sizeof dist); //初始化距離 0x3f代表無限大
dist[1]=0; //第一個點到自身的距離爲0
for(int i=0;i<n;i++) //有n個點所以要進行n次 迭代
{
int t=-1; //t存儲當前訪問的點
for(int j=1;j<=n;j++) //這裏的j代表的是從1號點開始
if(!st[j]&&(t==-1||dist[t]>dist[j]))
t=j;
st[t]=true;
for(int j=1;j<=n;j++) //依次更新每個點所到相鄰的點路徑值
dist[j]=min(dist[j],dist[t]+g[t][j]);
}
if(dist[n]==0x3f3f3f3f) return -1; //如果第n個點路徑爲無窮大即不存在最低路徑
return dist[n];
}
int main()
{
cin>>n>>m;
memset(g,0x3f,sizeof g); //初始化圖 因爲是求最短路徑
//所以每個點初始爲無限大
while(m--)
{
int x,y,z;
cin>>x>>y>>z;
g[x][y]=min(g[x][y],z); //如果發生重邊的情況則保留最短的一條邊
}
cout<<Dijkstra()<<endl;
return 0;
}