当前位置:   article > 正文

第K短路(A*算法)

第K短路(A*算法)

给定一张 N个点(编号 1,2…N),M条边的有向图,求从起点 S到终点 T 的第 K 短路的长度,路径允许重复经过点或边。

注意: 每条最短路中至少要包含一条边。

输入格式

第一行包含两个整数 N 和 M。

接下来 M 行,每行包含三个整数 A,B, 和 L,表示点 A 与点 B 之间存在有向边,且边长为 L。

最后一行包含三个整数 S,T 和 K,分别表示起点 S,终点 T 和第 K 短路。

输出格式

输出占一行,包含一个整数,表示第 K 短路的长度,如果第 K 短路不存在,则输出 −1−1。

数据范围

1≤S,T≤N≤1000,
0≤M≤10^4,
1≤K≤1000,
1≤L≤100。

输入样例:

  1. 2 2
  2. 1 2 5
  3. 2 1 4
  4. 1 2 2

输出样例: 

14

A*算法核心思想: 反向计算最短路到终点的估计值

注意:当起点和终点一样时,K++

f [x]=h [x] + g [x] (起点到终点的估计距离 = 起点到x的真实距离 + x到终点的估计距离

x到终点的估计距离我们可以通过Dijkstra算法逆向求出终点到各点的最短距离:

  1. void Dijkstra()
  2. {
  3. priority_queue<PII,vector<PII>,greater<PII>> heap;
  4. heap.push({0,T});
  5. memset(dist,0x3f,sizeof dist);
  6. dist[T]=0;
  7. while(heap.size())
  8. {
  9. auto it=heap.top();heap.pop();
  10. int distance=it.x,t=it.y;
  11. if(st[t])continue;
  12. st[t]=true;
  13. for(int i=rh[t];i!=-1;i=ne[i])
  14. {
  15. int j=e[i];
  16. if(dist[j]>distance+w[i])
  17. {
  18. dist[j]=distance+w[i];
  19. heap.push({dist[j],j});
  20. }
  21. }
  22. }
  23. }

接着就是从起点开始计算到终点的距离,我们需要将起点到终点距离小的优先出队,同一个点第几次出队就是第几短的路,那么就需要用到小顶堆了。

  1. int star()
  2. {
  3. if(dist[S]==0x3f3f3f3f) return -1;//若终点无法到达起点则返回-1
  4. priority_queue<PIII,vector<PIII> ,greater<PIII>> heap;
  5. heap.push({dist[S],{0,S}});
  6. while(heap.size())
  7. {
  8. auto it=heap.top();heap.pop();
  9. int distance=it.y.x,t=it.y.y;
  10. cnt[t]++;
  11. if(cnt[T]==K) return distance;//若终点第K次出队说明是第K短路
  12. for(int i=h[t];i!=-1;i=ne[i])
  13. {
  14. int j=e[i];
  15. if(cnt[j]<K)
  16. {
  17. //起点到j的距离+j到终点的估计距离
  18. heap.push({distance+w[i]+dist[j],{distance+w[i],j}});
  19. }
  20. }
  21. }
  22. return -1;
  23. }

完整代码:

  1. #include<iostream>
  2. #include<queue>
  3. #include<vector>
  4. #include<cstring>
  5. using namespace std;
  6. #define x first
  7. #define y second
  8. typedef pair<int,int> PII;
  9. typedef pair<int,PII> PIII;
  10. const int N=2e4+5;
  11. int h[N],rh[N],e[N],ne[N],w[N],idx;
  12. int dist[N],cnt[N],n,m,S,T,K;
  13. bool st[N];
  14. void add(int h[],int a,int b,int c)
  15. {
  16. e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
  17. }
  18. void Dijkstra()
  19. {
  20. priority_queue<PII,vector<PII>,greater<PII>> heap;
  21. heap.push({0,T});
  22. memset(dist,0x3f,sizeof dist);
  23. dist[T]=0;
  24. while(heap.size())
  25. {
  26. auto it=heap.top();heap.pop();
  27. int distance=it.x,t=it.y;
  28. if(st[t])continue;
  29. st[t]=true;
  30. for(int i=rh[t];i!=-1;i=ne[i])
  31. {
  32. int j=e[i];
  33. if(dist[j]>distance+w[i])
  34. {
  35. dist[j]=distance+w[i];
  36. heap.push({dist[j],j});
  37. }
  38. }
  39. }
  40. }
  41. int star()
  42. {
  43. if(dist[S]==0x3f3f3f3f) return -1;
  44. priority_queue<PIII,vector<PIII> ,greater<PIII>> heap;
  45. heap.push({dist[S],{0,S}});
  46. while(heap.size())
  47. {
  48. auto it=heap.top();heap.pop();
  49. int distance=it.y.x,t=it.y.y;
  50. cnt[t]++;
  51. if(cnt[T]==K) return distance;
  52. for(int i=h[t];i!=-1;i=ne[i])
  53. {
  54. int j=e[i];
  55. if(cnt[j]<K)
  56. {
  57. heap.push({distance+w[i]+dist[j],{distance+w[i],j}});
  58. }
  59. }
  60. }
  61. return -1;
  62. }
  63. int main()
  64. {
  65. cin>>n>>m;
  66. memset(h,-1,sizeof h);
  67. memset(rh,-1,sizeof rh);
  68. while(m--)
  69. {
  70. int a,b,c;cin>>a>>b>>c;
  71. add(h,a,b,c);
  72. add(rh,b,a,c);
  73. }
  74. cin>>S>>T>>K;
  75. if(S==T) K++;
  76. Dijkstra();
  77. cout<<star();
  78. return 0;
  79. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/232641
推荐阅读
相关标签
  

闽ICP备14008679号