[关闭]
@zsh-o 2018-10-22T11:01:50.000000Z 字数 2045 阅读 872

迪杰斯特拉(dijkstra) + 弗洛伊德(floyd)

算法


  1. /*
  2. 6 8
  3. 0 5 100
  4. 0 4 30
  5. 0 2 10
  6. 1 2 5
  7. 2 3 50
  8. 3 5 10
  9. 4 3 20
  10. 4 5 60
  11. */
  12. #include <stdio.h>
  13. #include <string.h>
  14. const int MAXN = 100;
  15. const int MAXV = 1e9 + 1;
  16. int _min(int a, int b){
  17. return a > b ? b : a;
  18. }
  19. int G[MAXN][MAXN];
  20. int N, M;
  21. // 从start节点开始
  22. // 图为G,邻接矩阵表示,节点个数为n
  23. int* dijkstra(int start);
  24. void Floyd();
  25. int main(){
  26. scanf("%d %d", &N,&M);
  27. for(int i=0; i<N; i++){
  28. for(int j=0; j<N; j++){
  29. G[i][j] = MAXV;
  30. }
  31. }
  32. int a, b, c;
  33. for(int i=0; i<M; i++){
  34. scanf("%d %d %d", &a, &b, &c);
  35. G[a][b] = c;
  36. }
  37. int* Lmin = dijkstra(0);
  38. for(int i=0; i<N; i++){
  39. int v = Lmin[i];
  40. if(v==MAXV){
  41. v = -1;
  42. }
  43. printf("%d\t", v);
  44. }
  45. printf("\n");
  46. Floyd();
  47. }
  48. int* dijkstra(int start){
  49. int* Lmin = new int[N];
  50. bool* visited = new bool[N];
  51. memset(visited, 0x00, sizeof(bool) * N);
  52. for(int i=0; i<N; i++){
  53. Lmin[i] = MAXV;
  54. }
  55. Lmin[start] = 0;
  56. int c_node = start;
  57. for(int i=0; i<N; i++){
  58. visited[c_node] = true;
  59. // 根据c_node更新没有访问过的Lmin的值
  60. for(int j=0; j<N; j++){
  61. if(visited[j] == false && G[c_node][j] < MAXV){
  62. Lmin[j] = _min(Lmin[j], Lmin[c_node] + G[c_node][j]);
  63. }
  64. }
  65. //
  66. for(int i=0; i<N; i++){
  67. int v = Lmin[i];
  68. if(v==MAXV){
  69. v = -1;
  70. }
  71. printf("%d\t", v);
  72. }
  73. printf("\n");
  74. for(int i=0; i<N; i++){
  75. printf("%d\t", visited[i]);
  76. }
  77. printf("\n");
  78. printf("----------------------------\n");
  79. //根据没有访问过的Lmin的最小值确定c_node
  80. int mmin = MAXV;
  81. for(int j=0; j<N; j++){
  82. if(visited[j] == false && Lmin[j] < mmin){
  83. c_node = j;
  84. mmin = Lmin[j];
  85. }
  86. }
  87. }
  88. return Lmin;
  89. }
  90. int D[MAXN][MAXN];
  91. int P[MAXN][MAXN];
  92. void Floyd(){
  93. // init D and P
  94. memcpy(D, G, sizeof(G));
  95. for(int i=0; i<N; i++){
  96. for(int j=0; j<N; j++){
  97. P[i][j] = j;
  98. }
  99. }
  100. for(int k=0; k<N; k++){
  101. for(int i=0; i<N; i++){
  102. for(int j=0; j<N; j++){
  103. int c = D[i][k] + D[k][j];
  104. if(c < D[i][j]){
  105. D[i][j] = c;
  106. P[i][j] = k;
  107. }
  108. }
  109. }
  110. }
  111. // Path
  112. int i=0, j=5, k;
  113. k = P[i][j];
  114. printf("%d", i);
  115. while(k != j){
  116. printf(" -> %d", k);
  117. k = P[k][j];
  118. }
  119. printf(" -> %d\n", j);
  120. printf("%d\n", D[i][j]);
  121. }
  1. 6 8
  2. 0 5 100
  3. 0 4 30
  4. 0 2 10
  5. 1 2 5
  6. 2 3 50
  7. 3 5 10
  8. 4 3 20
  9. 4 5 60
  10. 0 -1 10 -1 30 100
  11. 1 0 0 0 0 0
  12. ----------------------------
  13. 0 -1 10 60 30 100
  14. 1 0 1 0 0 0
  15. ----------------------------
  16. 0 -1 10 50 30 90
  17. 1 0 1 0 1 0
  18. ----------------------------
  19. 0 -1 10 50 30 60
  20. 1 0 1 1 1 0
  21. ----------------------------
  22. 0 -1 10 50 30 60
  23. 1 0 1 1 1 1
  24. ----------------------------
  25. 0 -1 10 50 30 60
  26. 1 0 1 1 1 1
  27. ----------------------------
  28. 0 -1 10 50 30 60
  29. 0 -> 4 -> 3 -> 5
  30. 60

迪杰斯特拉是单源最短路,时间复杂度为,每次确定一个最小节点,如果需要输出单源最短路径,需要需要有一个Path[N]数组Path[i]保存最小节点为i时的中间节点

Fold算法求多源最短需要用一个D矩阵和P矩阵,D[i][j]为源为i目的为j的最小值,P[i][j]表示愿为i目的为j达到最小时的中间节点

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注