POJ2449-A*算法-第k短路

(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦

题意:传送门

 原题目描述在最下面。
 给你一个有向图,求指定节点间的第k短路。

思路:

 先反向跑出从终点开始的到每个节点的最短距离。
 乐观估计函数(f(n) = g(n) + h'(n))(g(n))表示到当前状态跑的距离,(h'(n))表示到目标状态还需要的距离。
 对于(A*)然后跑一遍(bfs)就可以了。

AC代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<assert.h>
#include<bitset>
#include<vector>
#include<queue>
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) (x)&(-(x))
#define all(x) (x).begin(),(x).end()
#define mk make_pair
#define pb push_back
#define fi first
#define se second
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int N = (int)1e3 +107;
int n, m, k, st, ed;
int dis[N],vis[N],time[N];
struct lp{
  int f,g,v;
  friend bool operator <(const lp &a,const lp &b){
    if(a.f==b.f)return a.g>b.g;
    return a.f>b.f;
  }
}aa,bb;
struct lh{
  int v,w,nex;
}cw[100000+5],rev[100000+5];
int head[N],tot,headd[N],tum;
int q[2500005];
void add(int u,int v,int w){
  cw[++tot].v=v;cw[tot].nex=head[u];cw[tot].w=w;
  head[u]=tot;

  rev[++tum].v=u;rev[tum].nex=headd[v];rev[tum].w=w;
  headd[v]=tum;
}
void spfa(){
  for(int i = 1; i <= n; i++) dis[i] = INF;
  memset(vis, 0, sizeof(vis));
  int h = 0, t = 1;
  q[0] = ed;
  dis[ed] = 0;
  while(h < t){
    int u = q[h++];
    vis[u] = 0;
    for(int i = headd[u] ; ~i ; i = rev[i].nex){
      int v = rev[i].v, w = rev[i].w;
      if(dis[v] > dis[u] + w){
        dis[v] = dis[u] + w;
        if(!vis[v]){
          q[t++] = v;
          vis[v] = 1;
        }
      }
    }
  }
}
int Astar(){
  if(dis[st]==INF)return -1;
  memset(time,0,sizeof(time));
  aa.v=st;aa.f=dis[st];aa.g=0;
  priority_queue<lp>Q;
  Q.push(aa);
  while(!Q.empty()){
    bb = Q.top();Q.pop();
    int u = bb.v;
    time[u]++;
    if(time[u]==k&&u==ed)return bb.g;
    if(time[u]>k)continue;
    for(int i=head[u];~i;i=cw[i].nex){
      int v = cw[i].v;
      aa.v = v;
      aa.g=bb.g+cw[i].w;
      aa.f=aa.g+dis[v];
      Q.push(aa);
    }
  }
  return -1;
}
int main(){
  while(~scanf("%d%d", &n, &m)){
    tot=tum=-1;
    memset(head,-1,sizeof(head));
    memset(headd,-1,sizeof(headd));
    for(int i = 0, u, v, w; i < m; ++i){
      scanf("%d%d%d", &u, &v, &w);
      add(u,v,w);
    }
    scanf("%d%d%d", &st, &ed, &k);
    spfa();
    if(st == ed)k++;
    printf("%d
", Astar());
  }
  return 0;
}

####原题目描述:
原文地址:https://www.cnblogs.com/Cwolf9/p/9513214.html