單源最短路徑(Dijkstra)O(n*n)
阿新 • • 發佈:2018-11-07
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define INF 1000000 //無窮大 #define MAXN 20 //頂點個數的最大值 int n; //頂點個數 int Edge[MAXN][MAXN]; //鄰接矩陣 int S[MAXN]; //Dijkstra演算法用到的三個陣列 int dist[MAXN]; int path[MAXN]; void Dijkstra(int v0) { int i,j,k; for(i = 0;i < n;i++){ dist[i] = Edge[v0][i]; S[i] = 0; if(i != v0&&dist[i] < INF) path[i] = v0; else path[i] = -1; } S[v0] = 1; dist[v0] = 0; //頂點v0加入到頂點集合S for(i = 0;i < n-1;i++){ int min = INF, u = v0; //選擇當前集合T中具有最短路徑的頂點u for(j = 0;j < n;j++){ if(!S[j]&&dist[j] < min){ u = j; min = dist[j]; } } S[u] = 1; //將頂點u加入到集合S,表示它的最短路徑已求得 //修改T集合中頂點的dist和path陣列元素值 for(k = 0;k < n;k++){ if(!S[k] && Edge[u][k] < INF&&dist[u]+Edge[u][k] < dist[k]){ dist[k] = dist[u] + Edge[u][k]; path[k] = u; } } } } int main() { int i,j; int u,v,w; //邊的起點和終點及權值 scanf("%d",&n); //讀入頂點個數n while(1){ scanf("%d%d%d",&u,&v,&w); //讀入邊的起點和終點 if(u == -1&&v == -1&&w == -1) break; Edge[u][v] = w; //構造鄰接矩陣 } for(i = 0;i < n;i++){ for(j = 0;j < n;j++){ if(i == j) Edge[i][j] == 0; else if(Edge[i][j] == 0) Edge[i][j] = INF; } } Dijkstra(0); //求頂點0到其他頂點的最短路徑 int shortest[MAXN]; //輸出最短路徑上的各個頂點時存放各個頂點的序號 for(i = 1;i < n;i++){ printf("%d\t",dist[i]); //輸出頂點0到頂點i的最短路徑長度 //以下程式碼用於輸出頂點0到頂點i的最短路徑 memset(shortest,0,sizeof(shortest)); int k = 0; //k表示shortest陣列中最後一個元素的下標 shortest[k] = i; while(path[shortest[k]] != 0){ k++; shortest[k] = path[shortest[k-1]]; } k++; shortest[k] = 0; for(j = k;j > 0;j--) printf("%d->",shortest[j]); printf("%d\n",shortest[0]); } return 0; } /**********示例 輸入: 6 0 2 5 0 3 30 1 0 2 1 4 8 2 5 7 2 1 15 4 3 4 5 3 10 5 4 18 -1 -1 -1 輸出: 20 0->2->1 5 0->2 22 0->2->5->3 28 0->2->1->4 12 0->2->5 ***************/