自然語言描述
-
定義三個數組,分別為
V:表示所有的頂點集 D:表示從起始點到其他各點的距離 S:為已求得的從源點出發的最短路徑長度的頂點的集合
-
設v0為起始點,若與v0直接連接的vi,則記錄其權值到D[i],否則記錄∞到D[i];
-
循環下列語句直至V-S為空集:
(1)遍歷D中的數據,若D[i]為最小值;記錄vi到S中
(2)更新D中的數據(遍歷vj∈(V-S), D[ j ] = MIN(D[ j ] , D[ i ] + D[vi到vj的距離] ));
偽代碼
算法:Dijkstra(G,v)v是起始點
輸入:G=(V,E)是帶權連通圖
輸出:D是含有起始點v到各點最短距離的數組
過程:
#define INF 0x7f7f7f7f
S ← { }
for i ←1 to |V| :
D[i] = INF
for every vi in V except v:
D[i] = min{ 所有的E(v , vi)};
while(|V-S| != 0){
//遍歷D中數據
vk = min{every D[i] in D};
S ← v[k]
//更新D中數據
for every D[i] in D:
D[i] = min{D[i], D[k] + E(k,i) };
}
輸出D
問題
Problem
Given a directed graph, compute all the shortest paths from the source to other vertices.
Input
The first line is the number of test cases.
For every test case, the first line is the number of node n, meaning nodes are 1,2,…,n.
The next line is the number of edges m, then m lines are followed, where each line is in the form of u v w, meaning (u,v) is an edge and it has weight w (>0).
The last line is the source vertex.
Output
For each test case, print all the shortest paths from the source s to other vertices (if the shortest path is finite) in the order of vertices in the following form (no spaces between):
s-1:d1
s-2:d2
…
Sample Input
2
2
1
1 2 5
1
5
6
1 2 4
1 3 6
2 3 1
4 5 1
3 1 1
5 4 2
2
Sample Output
1-1:0
1-2:5
2-1:2
2-2:0
2-3:1
代碼實現
#include <stdio.h>
#define INF 0x7f7f7f7f
#define SIZE 100
void Dijkstra(int matrix[][SIZE],int vertex, int dis[],int startingpoint);
int min(int a, int b)return a>b?b:a;
int mindis(int dis[],int vertex,int usedvertex[]);
int main(){
int times; //次數
scanf("%d",×);
for(int t = 0; t < times; t++){
int vertex = 0; // 點數
int edge = 0; // 邊數
scanf("%d",&vertex);
scanf("%d",&edge);
int matrix[SIZE][SIZE];
for(int i = 0; i <= vertex; i++){
for(int j = 0; j <= vertex; j++){
matrix[i][j] = INF;
}
}
//輸入矩陣
for(int i = 0; i < edge; i++ ){
int x,y,weight;
scanf("%d",&x);
scanf("%d",&y);
scanf("%d",&weight);
if(weight < matrix[x][y]){
matrix[x][y] = weight;
}
}
int startingpoint;
scanf("%d",&startingpoint);
//distance 數組
int dis[vertex+1] ={0};
for(int i = 1; i <= vertex; i ++){
dis[i] = matrix[startingpoint][i];
}
//Dijkstra
Dijkstra(matrix,vertex,dis,startingpoint);
//輸出
for(int i = 1; i <= vertex; i++){
if(dis[i]!=INF)printf("%d-%d:%d\n",startingpoint,i,dis[i]);
}
}
}
//返回dis數組里的未被記錄的最小值
int mindis(int dis[],int vertex,int usedvertex[]){
int min=INF, minvertex;
for(int i = 1 ; i <= vertex; i++){
if(usedvertex[i]==1)continue;
if(dis[i]<min){
min = dis[i];
minvertex = i;
}
}
return minvertex;
}
void Dijkstra(int matrix[][SIZE],int vertex, int dis[],int startingpoint){
int usedvertex[vertex+1] = {0}; //記錄已確定最小值的點
int count = vertex-1;
usedvertex[0] = 1;
usedvertex[startingpoint] = 1;
while(count !=0 ){
//第一步,取新的點
int newvertex = mindis(dis,vertex,usedvertex);
usedvertex[newvertex] = 1;
//第二部,更新距離數組
for(int i = 1; i <= vertex; i++){
dis[i] = min(dis[i],matrix[newvertex][i]+dis[newvertex]);
}
count --;
}
dis[startingpoint] = 0;
}