如何求任意兩點之間的最短路徑呢?在之前的學習裡,知道可以通過深搜或者廣搜求出兩點之間的最短路徑。但學習了dijkstra這個新的演算法以後,會更方便。
dijkstra演算法的基本思想:
每次找到離源點最近的乙個頂點,然後以該頂點為中心進行擴充套件,最終得到源點到其餘所有點的最短路徑。
基本步驟:
1. 將所有頂點分為兩部分:已知最短路程的頂點集合p和未知最短路徑的頂點集合q。最開始,已知最短路徑的頂點集合p中只有源點乙個頂點。我們這裡用乙個book陣列來記錄哪些頂點再集合p中。例如對於某個頂點i,如果book[i]為1則表示這個頂點再集合p中,如果book[i]為0則表示這個頂點再集合q中。
2. 設定源點x到自己的最短路徑為0即 dis[x]=0。若存在有源點能直接到達的頂點i,則把dis[i]設為g[x][i]。同時把所有其他(源點不能直接到達的)頂點的最短路徑設為∞。
3. 在集合q的所有頂點中選擇乙個離源點x最近的頂點u(即dis[u]最小)加入到集合p。並考察所有以點u為起點的邊,對每一條邊進行鬆弛操作。例如存在一條從u到v的邊,那麼可以通過將u->v新增到尾部來拓展一條從s到v的路徑,這條路徑的長度時dis[u]+g[u][v]。如果這個值比目前已知的dis[v]的值要小,我們可以用新值來替代當前dis[v]中的值。
4. 重複第3步,如果集合q為空,演算法結束。最終dis陣列中的值就是源點到所有頂點的最短路徑。
其實它的過程是很簡單的,下面是**的實現:
floyd-warshall:
#includeint main()
//floyd-warshall核心語句
for(k = 1; k <= n; k ++)
for(i = 1; i <= n; i ++)
for(j = 1; j <= n; j ++)
if(e[i][j] > e[i][k] + e[k][j])
e[i][j] = e[i][k] + e[k][j];
for(i = 1; i <= n; i ++)
return 0;
}
dijkstra:
#includeint m,n,e[10][10],dis[10],book[10];
int inf = 99999999;
void dijkstra(int x)
dis[x] = 0;
book[x] = 1;
for(i = 1; i < n; i ++)
book[u] = 1;
for(j = 1; j <= n; j ++)
if(book[j] == 0 && dis[j] > dis[u] + e[u][j])
dis[j] = dis[u] + e[u][j]; }}
int main()
dijkstra(1);
return 0;
}
另外,還有乙個負權邊的情況,就是在給出的距離上會出現負的,此時就不能再用上面的**來實現了,因為擴充套件到負權邊的時候會產生更短的路程,有可能就破壞了已經更新的點路程不會改變的性質。
此時,用bellman-ford演算法就能很好的解決了。
**實現:
#includeint main()
if(count == 1)
break;
} flag = 0;
for(i =1; i <= m; i ++)
if(dis[v[i]] > dis[u[i]] + w[i])
flag = 1;
if(flag == 1)
printf("此圖含有負權迴路");
return 0;
}
最短路 Dijkstra演算法
dijksitra演算法求最短路僅僅適用於不存在右邊是負權的情況 bellman ford演算法沒有這乙個限制 主要特點是從起點為中心向外層層擴充套件,直到擴充套件到終點為止。即乙個最短路路徑中經過的所有點這條路均是其最短路。反證法易證 dijkstra基本思路 找到最短距離已經確定的頂點,從它出發...
dijkstra最短路演算法
dijkstra演算法 1.定義概覽 dijkstra 迪傑斯特拉 演算法是典型的單源最短路徑演算法,用於計算乙個節點到其他所有節點的最短路徑。主要特點是以起始點為中心向外層層擴充套件,直到擴充套件到終點為止。dijkstra演算法是很有代表性的最短路徑演算法,在很多專業課程中都作為基本內容有詳細的...
最短路 Dijkstra演算法
這是一類求單源最短路的演算法,也就是求某乙個頂點到其他所有頂點的最短路。它是按照最短路徑遞增的順序來計算的。先說一下大體思路 將圖中的頂點分為兩個集合,s,v s。s儲存已經求出最短路徑的頂點,v s儲存未求出最短路的頂點。然後演算法就是不斷額的求出v s中頂點的最短路,然後把它加入s中,直到所有頂...