Dijkstra模板(最短路径)

  1. /***********************************************************************************************
  2. 注意相应权值不能为负,且时间复杂度较高
  3. 算法步骤如下:
  4. 1. 初始时令 S={V0},T={其余顶点},T中顶点对应的距离值
  5. 若存在<V0,Vi>,d(V0,Vi)为<V0,Vi>弧上的权值
  6. 若不存在<V0,Vi>,d(V0,Vi)为∞
  7. 2. 从T中选取一个其距离值为最小的顶点W且不在S中,加入S
  8. 3. 对其余T中顶点的距离值进行修改:若加进W作中间顶点,从V0到Vi的距离值缩短,则修改此距离值
  9. 重复上述步骤2、3,直到S中包含所有顶点,即W=Vi为止
  10. ************************************************************************************************/
  11. #include <stdio.h>
  12. #define INF 0x7fffffff
  13. #define MAX 1100
  14. int dist[MAX], pre[MAX], path[MAX][MAX];
  15. bool sign[MAX];
  16. void initialize(int n) //初始化
  17. {
  18. for(int i=1; i<=n; i++)
  19. {
  20. {
  21. //pre[i] = 0;
  22. dist[i] = INF; //将距离开始全变为最大
  23. //sign[i] = false;
  24. }
  25. for(int j=1; j<=n; j++)
  26. path[i][j] = INF; //图初始
  27. }
  28. }
  29. void dijkstra(int n, int source )
  30. {
  31. for(int i=1; i<=n; i++)
  32. {
  33. dist[i] = path[source][i]; //将与源点有关的点的距离加入dist
  34. sign[i] = false;
  35. if(dist[i] == INF) //确定有关系的点的前驱,无则为0
  36. pre[i] = 0;
  37. else
  38. pre[i] = source;
  39. }
  40. dist[source] = 0; //源点自身长度为0
  41. sign[source] = 1;
  42. /*
  43. 依次将未放入sign集合的结点中,取dist[]最小值的结点,放入结合sign中
  44. 一旦sign包含了所有n中顶点,dist就记录了从源点到所有其他顶点之间的最短路径长度
  45. */
  46. for(int i=2; i<=n; i++)
  47. {
  48. int min = INF;
  49. int current = source;
  50. for(int j=1; j<=n; j++) //找出当前未使用点j的dist[j]的最小值
  51. {
  52. if( (!sign[j]) && dist[j] < min )
  53. {current = j; min = dist[j];}
  54. }
  55. sign[current] = true; //表示当前点最短距离已经找到
  56. for(int j=1; j<=n; j++) //更新当前点到未找到点的距离
  57. if( (!sign[j]) && path[current][j] < INF)
  58. {
  59. int newdist = dist[current] + path[current][j];
  60. if(newdist < dist[j] )
  61. {dist[j] = newdist; pre[j] = current;}
  62. }
  63. }
  64. }
  65. void search_path(int n, int start, int end)
  66. {
  67. int road[MAX];
  68. int total = 1;
  69. road[total++] = end; //从后向前查找
  70. int current = pre[end]; //路径存在pre中
  71. while( current != start) //递归查找,类似并查集
  72. {
  73. road[total++] = current;
  74. current = pre[current];
  75. }
  76. road[total] = start; //最后的开始点存入
  77. for(int i=total; i>=1; i--) //输出
  78. {
  79. if( i!=1)
  80. printf("%d ->", road[i]);
  81. else
  82. printf("%d\n", road[i]);
  83. }
  84. }
  85. void input(int line)
  86. {
  87. int a, b, weight;
  88. for(int i=0; i<line; i++)
  89. {
  90. scanf("%d%d%d", &a, &b, &weight);
  91. if(path[a][b] > weight) //有多条路,保存最短的那条
  92. {
  93. path[a][b] = weight;
  94. path[b][a] = weight; //无向图双向
  95. }
  96. }
  97. }
  98. int main()
  99. {
  100. int n, line;
  101. scanf("%d%d", &n, &line);
  102. initialize(n);
  103. input(line);
  104. dijkstra(n, 1);
  105. printf("%d\n\n", dist[n]);
  106. search_path(n, 1, n);
  107. return 0;
  108. }





附件列表

     

    posted @ 2015-01-29 15:38  sober_reflection  阅读(158)  评论(0编辑  收藏  举报