標籤:最小產生樹演算法之 dijkstra演算法
Dijkstra演算法
Dijkstra演算法是典型最短路演算法,用於計算一個節點到其他所有節點的最短路徑。主要特點是以起始點為中心向外層層擴充,直到擴充到終點為止。Dijkstra演算法能得出最短路徑的最優解,但由於它遍曆計算的節點很多,所以效率低。
Dijkstra演算法是用來求任意兩個頂點之間的最短路徑。在該演算法中,我們用鄰接矩陣來儲存圖。在該程式中設定一個二維數組來儲存任意兩個頂點之間的邊的權值。可以將任意一個圖的資訊通過鍵盤輸入,讓後在輸入要尋找的兩個頂點,程式可以自動求出這兩個頂點之間的最短路徑。
演算法思想
s為源,Map[u,v] 為點u 和v 之間的邊的長度,結果儲存在 dis[];
初始化:源的距離dis[s]設為0,其他的點距離設為無窮大,同時把所有的點狀態設為沒有擴充過。
迴圈n-1次:
1. 利用標記變數數組 在沒有擴充過的點中取一距離最小的點u,並將其狀態設為已擴充。
2. 對於每個與u相鄰的點v,如果dis[u] + Map[u,v] < dis[v],那麼把dist[v]更新成更短的距離dis[u] + Map[u,v] 。此時到點v的最短路徑上,前一個節點即為u。
結束:此時對於任意的u,dist[u]就是s到u的距離。
附 Hdu 2544 最短路
做題思想
建立一個Map的二維數組 裡面的初始值改為一個INF(大數) 把從A到B 的路徑長度儲存進去
建立一個Dis 的數組 儲存Map[ s ][ 0 →n ]裡的資料 迴圈N-1次 每次標記一個dis中最小的標號 並用
if(!flag[i] && dis[i]>dis[t] + Map[t][i]) 該標號更新Dis 數組
更新過後 dis[ x ] 即為源點S的到x 的最短距離
代碼
#include<stdio.h> // Dijkstra 演算法#include<iostream>#include<string.h>#define INF 10000000using namespace std;int Map[101][101],dis[110];int n ,m;void Dijkstra(){ int i,j,D = 0; bool flag[110]; memset(flag,0,sizeof(flag)); //標記數組 for(i=1; i<=n; i++) dis[i]=Map[1][i]; //與1處的距離 每一個i代表自身與1的距離 for(i=1; i<n; i++) //每次迴圈標記一個點 一共標記n-1個點 { int temp = INF; for(j=1; j<=n; j++) //找出dis數組中的最小的那個值 位置用D記錄下來 if(!flag[j]&&dis[j]<temp) { temp = dis[j]; D = j; } flag[D] = 1; //把該點標記 for(j=1; j<=n; j++) //更新dis數組 以D { if(!flag[j]&&dis[j] > Map[D][j]+dis[D]) dis[j] = Map[D][j]+dis[D]; } }}int main(){ int i,j,x,y,z; while(scanf("%d %d",&n,&m)!=EOF&&(m||n)) { for(i=0; i<101; i++) { //地圖清空初始化為一個大數 for(j=0; j<101; j++) Map[i][j] = INF; Map[i][i]=0; } for(i=1; i<=m; i++) { cin >> x >> y >> z; //輸入 if(Map[x][y] > z) //如果再次輸入的 比之前的小,覆蓋 Map[x][y]=Map[y][x] = z; } Dijkstra(); printf("%d\n",dis[n]); //全部迴圈過後,dis【n】的值即為從1到n 的距離; } return 0;}
附:
ACM假期集訓感悟:
一轉眼半個月過去了,上午聽師哥講演算法,看書;下午刷題,總結;
別人都說我們程式員苦,累;還有一個綽號 “屌絲程式猿”;
可我並不這麼認為,每天學習演算法鍛煉思維,刷題提高代碼能力和邏輯思維
在ACM訓練中,最開心的時候就是花老長時間去改錯,WA一遍又一遍,終於該出了最後一個BUG ,AC!
心情就無比的舒暢,看窗外的樹葉是那樣的翠綠,天是那樣的蔚藍。
在大學生活中能過的如此充實,有動力,有目標,朝著目標一步一步的走去, 是多麼幸福的一件事
在這裡,送出我的一句話:
整個世界填滿不了十八歲男孩子的雄心和夢。