<学习笔记> A*算法求第k短路

一条前往题面的隧道

简洁题面

      • 第一行给出N(点数),M(边数)(1 <= N <= 1000, 0 <= M <= 100000).。
      • 下面的M行每行给出三个数Ai,Bi,Ti,表示从A到B有一条权值为T的单向边。
      • 最后给出S,T,K,表示求S到T的第K短路。
      • special:
        • 起点与终点相同时,S–>S (d=0) 不能算作一条路。
        • 题目会给出多组数据。
        • 即使有好几条路到T的距离都相同,它们仍被记为不同的路。

正解

      A*算法

     记g[i]为起点s到i的距离,h[i] (期望值)为终点T到i的最短路,用SPFA预处理出来。采用dijkstra的做法,从S开始处理,每次从堆中弹出当前h[i]+g[i]最小的点。当终点T被弹出第K次时,此时的g[i]即为S到T的第K短路。

  

代码qwq

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cmath>
  6 #include<queue>
  7 using namespace std;
  8 
  9 int N,M,a,b,c,S,T,K,cnt;
 10 int first[1010],next[100010],h[1010];
 11 bool used[1010];
 12 
 13 struct maple{
 14     int f,t,d;
 15 }Rode[100010];
 16 
 17 struct leaf{
 18     int f,g,h;
 19     bool operator <(const leaf &a) const{
 20          return a.g+a.h<g+h;    
 21     }
 22 }; 
 23 
 24 void Build(int f,int t,int d)
 25 {
 26     Rode[++cnt]=(maple){f,t,d};
 27     next[cnt]=first[f];
 28     first[f]=cnt;
 29 }
 30 
 31 void SPFA()
 32 {
 33     queue<int> q; // 
 34     memset(h,63,sizeof(h));
 35     memset(used,0,sizeof(used));
 36     h[T]=0;
 37     used[T]=1;
 38     q.push(T);
 39     while(!q.empty())
 40     {
 41         int A=q.front();
 42         q.pop();
 43         used[A]=0;
 44         for(int i=first[A];i;i=next[i])
 45            if(h[Rode[i].t]>h[A]+Rode[i].d)
 46            {
 47                   h[Rode[i].t]=h[A]+Rode[i].d;
 48                   if(!used[Rode[i].t])
 49                   {
 50                          used[Rode[i].t]=1;
 51                          q.push(Rode[i].t);
 52                   }
 53            } 
 54     }
 55 }
 56 
 57 int search()
 58 {
 59      if(h[S]>1e9+7) return -1; // 从起点无法到终点 
 60      if(S==T) ++K; 
 61      priority_queue<leaf> Q; // 定义在函数里不用清空qwq 
 62      Q.push((leaf){S,0,h[S]});
 63      while(!Q.empty())
 64      {
 65          leaf A=Q.top();
 66          Q.pop();
 67          if(A.f==T)
 68          {
 69               --K;
 70               if(K==0) return A.g;
 71          }
 72          for(int i=first[A.f];i;i=next[i])
 73              Q.push((leaf){Rode[i].t,A.g+Rode[i].d,h[Rode[i].t]});
 74      } 
 75      return -1; // 没找到第k短路也不行 
 76 }
 77 int main()
 78 {
 79     while(scanf("%d%d",&N,&M)!=EOF)
 80     {
 81          cnt=0;
 82          memset(first,0,sizeof(first));
 83          memset(next,0,sizeof(next));
 84          for(int i=1;i<=M;++i)
 85          { 
 86              scanf("%d%d%d",&a,&b,&c);
 87              Build(b,a,c);
 88          }
 89          scanf("%d%d%d",&S,&T,&K);   
 90          SPFA();
 91          memset(first,0,sizeof(first));
 92          memset(next,0,sizeof(next));
 93          cnt=0;
 94          for(int i=1;i<=M;++i)
 95              Build(Rode[i].t,Rode[i].f,Rode[i].d); // 重新建边 
 96          int ans=search();
 97          printf("%d\n",ans);
 98     }
 99     return 0;
100 }

 

posted @ 2017-11-07 13:30  loi_maple  阅读(528)  评论(0编辑  收藏  举报