单源最短路径
本文章使用狄克斯特拉算法,该算法不可以应用于包含负权值的图。具有负权值的图可以套用贝尔曼-福特算法或弗洛伊德算法来处理
输入:第一行输入G的顶点数n。接下来n行按如下格式输入各顶点u的邻接表。
u k v1 c1 v2 c2 ... vk ck
G中的各顶点编号分别为0至n-1。u代表顶点的编号,k代表u的出度。vi(i = 1, 2, ... , k)代表与u相邻顶点的编号,ci代表u到vi的有向边的权值。
输出:按顺序输出个顶点编号v及距离d[v],相邻数据间用1个空格隔开。
1 #include<iostream> 2 using namespace std; 3 4 static const int MAX = 100; 5 static const int INFTY = (1<<21); 6 static const int WHITE = 0; 7 static const int GRAY = 1;//代表预选 8 static const int BLACK = 2;//代表入选 9 10 int n, M[MAX][MAX]; 11 //狄克斯特拉 12 void dijkstra() { 13 int minv; 14 /* 15 1.d[n]用于记录起点s到v的最短路径成本 16 2.p[n]用于记录顶点v在最短路径树中的父节点 17 */ 18 int d[MAX], color[MAX], p[MAX]; 19 20 //初始化 21 for(int i = 0; i < n; i++) { 22 d[i] = INFTY; 23 p[i] = -1; 24 color[i] = WHITE; 25 } 26 d[0] = 0; 27 color[0] = GRAY; 28 29 while(1) { 30 minv = INFTY; 31 int u = -1; 32 for(int i = 0; i < n; i++) { 33 if(minv > d[i] && color[i] != BLACK) { 34 u = i; 35 minv = d[i]; 36 } 37 } 38 //遍历结束则退出循环 39 if(u == -1) break; 40 color[u] = BLACK; 41 42 for(int v = 0; v < n; v++) { 43 if(color[v] != BLACK && M[u][v] != INFTY) { 44 if(d[v] > d[u] + M[u][v]) { 45 d[v] = d[u] + M[u][v]; 46 color[v] = GRAY; 47 p[v] = u; 48 } 49 } 50 } 51 } 52 53 for(int i = 0; i < n; i++) { 54 cout << i << " " << (d[i] == INFTY? -1 : d[i]) << endl; 55 } 56 } 57 58 int main() { 59 cin >> n; 60 //初始化 61 for(int i = 0; i < n; i++) { 62 for(int j = 0; j < n; j++) { 63 M[i][j] = INFTY; 64 } 65 } 66 67 int k, c, u, v; 68 for(int i = 0; i < n; i++) { 69 cin >> u >> k; 70 for(int j = 0; j < k; j++) { 71 cin >> v >> c; 72 M[u][v] = c; 73 } 74 } 75 76 dijkstra(); 77 78 return 0; 79 } 80 81 /* 82 5 83 0 3 2 3 3 1 1 2 84 1 2 0 2 3 4 85 2 3 0 3 3 1 4 1 86 3 4 2 1 0 1 1 4 4 3 87 4 2 2 1 3 3 88 */