有代价的单源最短路径

问题:有代价的单源最短路径,并要求存储路径。(求最短的路径,并使代价最小)

特点:

* 存储路径:决定了难以用dijkstra,可以用flody,用path[i][j]表示 i 想走到 j 迈出的第一步。假设k是 i->j 的中间节点,更新时候用path[i][j] = path[i][k],具体做法见link。但是flody比较耗时(O(N^3))

* 有代价:如果想用flody的话,有要求代价最小,就需要将最短路相等的都记录下来。边一多代价更上去了。所以还是dfs比较方便。

例题:

PAT 1018(http://pat.zju.edu.cn/contests/pat-a-practise/1018)

这道题关键要想到用dfs,就好做了。Code:

[cpp] view plain copy

  1. #include<iostream>
  2. #include<memory.h>
  3. #include<vector>
  4. using namespace std;
  5. #define N 505
  6. int map[N][N];
  7. vector<int> path,min_path;
  8. int bike[N];
  9. bool visit[N];
  10. #define INF 10000000
  11. int dest,n,req;//req:require
  12. int min_d,min_bring,min_back;
  13. int cur_d,cur_bring,cur_back;
  14. void dfs(int p)
  15. {
  16. int i;
  17. if(p==dest)
  18. {
  19. if(cur_d<min_d ||
  20. cur_d==min_d && cur_bring < min_bring||
  21. cur_d == min_d && cur_bring == min_bring && cur_back<min_back)
  22. {
  23. min_d = cur_d;
  24. min_bring = cur_bring;
  25. min_back = cur_back;
  26. min_path = path;
  27. }
  28. return;
  29. }
  30. else
  31. {
  32. for(i=0;i<=n;i++)
  33. {
  34. if(!visit[i]&&map[p][i]!=INF)
  35. {
  36. cur_d += map[p][i];
  37. visit[i] = true;
  38. path.push_back(i);
  39. if(bike[i]<req)
  40. {
  41. if(cur_back >= req-bike[i])
  42. {
  43. cur_back -= (req-bike[i]);
  44. dfs(i);
  45. cur_back += (req-bike[i]);
  46. }
  47. else
  48. {
  49. int t = cur_back;
  50. cur_bring += req-bike[i] - cur_back;
  51. cur_back = 0;
  52. dfs(i);
  53. cur_back = t;
  54. cur_bring -= req-bike[i] - cur_back;
  55. }
  56. }
  57. else
  58. {
  59. cur_back += bike[i]-req;
  60. dfs(i);
  61. cur_back -= (bike[i]-req);
  62. }
  63. path.pop_back();
  64. visit[i] = false;
  65. cur_d-=map[p][i];
  66. }
  67. }
  68. }
  69. }
  70. int main()
  71. {
  72. int cm,m,i,j,t,a,b;
  73. scanf("%d%d%d%d",&cm,&n,&dest,&m);
  74. req = cm/2;
  75. for(i=0;i<n;i++)
  76. scanf("%d",&bike[i+1]);
  77. memset(visit,false,sizeof(visit));
  78. visit[0] = true;
  79. for(i=0;i<=n;i++)
  80. for(j=0;j<=n;j++)
  81. map[i][j] = INF;
  82. for(i=0;i<m;i++)
  83. {
  84. scanf("%d%d%d",&a,&b,&t);
  85. if(map[a][b]>t)
  86. map[a][b] = map[b][a] = t;
  87. }
  88. min_d = min_bring = min_back = INF;
  89. cur_d = cur_bring = cur_back = 0;
  90. path.push_back(0);
  91. dfs(0);
  92. cout<<min_bring<<" ";
  93. printf("%d",min_path[0]);
  94. for(i=1;i<min_path.size();i++)
  95. printf("->%d",min_path[i]);
  96. cout<<" "<<min_back<<endl;
  97. return 0;
  98. }

from: http://blog.csdn.net/abcjennifer/article/details/19830187

时间: 2024-08-02 13:31:49

有代价的单源最短路径的相关文章

Dijkstra算法详细(单源最短路径算法)

介绍 对于dijkstra算法,很多人可能感觉熟悉而又陌生,可能大部分人比较了解bfs和dfs,而对dijkstra和floyd算法可能知道大概是图论中的某个算法,但是可能不清楚其中的作用和原理,又或许,你曾经感觉它很难,那么,这个时候正适合你重新认识它. Dijkstra能是干啥的? Dijkstra是用来求单源最短路径的 就拿上图来说,假如直到的路径和长度已知,那么可以使用dijkstra算法计算南京到图中所有节点的最短距离. 单源什么意思? 从一个顶点出发,Dijkstra算法只能求一个顶

Dijkstra算法求单源最短路径

1.最短路径 在一个连通图中,从一个顶点到另一个顶点间可能存在多条路径,而每条路径的边数并不一定相同.如果是一个带权图,那么路径长度为路径上各边的权值的总和.两个顶点间路径长度最短的那条路径称为两个顶点间的最短路径,其路径长度称为最短路径长度. 最短路径在实际中有重要的应用价值.如用顶点表示城市,边表示两城市之间的道路,边上的权值表示两城市之间的距离.那么城市A到城市B连通的情况下,哪条路径距离最短呢,这样的问题可以归结为最短路径问题. 求最短路径常见的算法有Dijkstra算法和Floyd算法

单源最短路径 dijkstra算法实现

本文记录一下dijkstra算法的实现,图用邻接矩阵表示,假设图为无向图,并且连通,有向图,不连通图的做法类似. 算法简述: 首先确定"单源"的源,假设是第0个顶点. 维护三个数组dist[], color[], path[],设其下标分别为0-i-n-1: dist[] 表示源点到顶点i的最短距离,在初始化时,如果源点到顶点i有路径,则初始化为路径的权重,否则初始化为INT_MAX: color[] 数组其实表示两个集合,即color[i]值为1的集合表示已经确定最短路径的点的集合,

数据结构之单源最短路径(迪杰斯特拉算法)-(九)

最开始接触最短路径是在数据结构中图的那个章节中.运用到实际中就是我在大三参加的一次美赛中,解决中国的水资源问题.所谓单源最短路径,就是一个起点到图中其他节点的最短路径,这是一个贪心算法. 迪杰斯特拉算法原理(百科): 按路径长度递增次序产生算法: 把顶点集合V分成两组: (1)S:已求出的顶点的集合(初始时只含有源点V0) (2)V-S=T:尚未确定的顶点集合 将T中顶点按递增的次序加入到S中,保证: (1)从源点V0到S中其他各顶点的长度都不大于从V0到T中任何顶点的最短路径长度 (2)每个顶

数据结构:单源最短路径--Dijkstra算法

Dijkstra算法 单源最短路径 给定一带权图,图中每条边的权值是非负的,代表着两顶点之间的距离.指定图中的一顶点为源点,找出源点到其它顶点的最短路径和其长度的问题,即是单源最短路径问题. Dijkstra算法 求解单源最短路径问题的常用方法是Dijkstra(迪杰斯特拉)算法.该算法使用的是贪心策略:每次都找出剩余顶点中与源点距离最近的一个顶点. 算法思想 带权图G=<V,E>,令S为已确定了最短路径顶点的集合,则可用V-S表示剩余未确定最短路径顶点的集合.假设V0是源点,则初始 S={V

dijkstra 两点的最短路径 单源 最短路径

思路以dist数组 来扩充  路径的访问,不断的刷新dist数组 设置一个顶点的集合s,并不断地扩充这个集合,一个顶点属于集合s当且仅当从源点到该点的路径已求出.开始时s中仅有源点,并且调整非s中点的最短路径长度,找当前最短路径点,将其加入到集合s,直到终点在s中.基本步骤:1.把所有结点分成两组:      第一组:包括已经确定最短路径的结点:      第二组:包括尚未确定最短路径的结点.2.开始时,第一组只包含起点,第二组包含剩余的点:3.用贪心的策略,按最短路径长度递增的顺序把第二组的结

单源最短路径 Bellman_ford 和 dijkstra

首先两个算法都是常用于 求单源最短路径 关键部分就在于松弛操作 实际上就是dp的感觉 if (dist[e.to] > dist[v] + e.cost) { dist[e.to] = dist[v] + e.cost; ... } bellman_ford O(E*V) 但是配合队列可以 有spfa 可以达到O(kE) http://www.360doc.com/content/13/1208/22/14357424_335569176.shtml 并且bellman_ford还适用于负边 并

数据结构与算法--单源最短路径算法之dijkstra

单源最短路径之dijkstra算法 最优子问题:dis(s,...,e)是s到e的最短路径,在这条路径上的所有点之间dis(pi,pj)距离是最小的. 算法思路: 首先初始化,dis[s][i]是s到i的距离,直接相连的就是其距离,不直接相连的就是无穷大 下面是算法主要模块: 1.选取dis[i]最小的点加入到P{S}中, 2.计算是否更新dis[j],j是和i直接相连的 3.重复以上步骤,直到e

单源最短路径、所有结点对的最短路径

算法核心:两个结点之间的一条最短路径包含着(包含于)其它的最短路径.[最短路径性质] 1.单源最短路径Dijkstra 思路:计算每个结点到源结点的距离,压入最小优先队列Q,对Q中的元素进行如下循环操作: 1.从队列Q中弹出最小元素u 2.将u并入S 3.对u的邻接表中每个结点v,调用Relax(u,v,w)更新结点v到源结点s的距离 直至Q为空. 伪代码: Initialize-Single-Source(G,s) for each vertex v in G.v v.d = MAX v.p