经典的第K短路,A*函数主要是估值函数的设计与分析,这个需要一定的经验,似乎启发式函数在ACM/ICPC中很少用到哦!
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int MAXN = 1010;
const int MAXM = 100010;
const int INF = 0x3f3f3f3f;
int first[MAXN], d[MAXN];
int first2[MAXN];
int n, m;
int cnt;
int s, e, k;
struct Edge
{
int v, next, w;
int f, g; //f = g + h;
bool operator < (const Edge &a) const
{
if(a.f == f) return a.g < g;
return a.f < f;
}
}edge[MAXM], edge2[MAXM];
inline void init()
{
cnt = 0;
memset(first, -1, sizeof(first));
memset(first2, -1, sizeof(first2));
}
inline void read_graph(int u, int v , int w)
{
edge[cnt].v = v, edge[cnt].g = w;
edge[cnt].next = first[u], first[u] = cnt;
edge2[cnt].v = u, edge2[cnt].w = w;
edge2[cnt].next = first2[v], first2[v] = cnt++;
} //建立正、反向图
void spfa(int src)
{
queue<int> q;
bool inq[MAXN] = {0};
for(int i = 1; i <= n; i++) d[i] = (i == src)? 0:INF;
q.push(src);
while(!q.empty())
{
int x = q.front(); q.pop();
inq[x] = 0;
for(int e = first2[x]; e != -1; e = edge2[e].next)
{
int v = edge2[e].v, w = edge2[e].w;
if(d[v] > d[x] + w)
{
d[v] = d[x] + w;
if(!inq[v])
{
inq[v] = 1;
q.push(v);
}
}
}
}
}
int A_STAR(int s, int e, int k)
{
int tot = 0;
priority_queue<Edge> Q;
struct Edge cur, next;
cur.v = s, cur.g = 0, cur.f = d[s];
if(s == e) k++; //当终点与起点相同时,0路径不算在第K短路径中,所以加1
if(d[s] == INF) return -1;
Q.push(cur);
while(!Q.empty())
{
cur = Q.top(); Q.pop();
int u = cur.v;
if(u == e)
{
tot++;
if(tot == k) return cur.g;
}
for(int e = first[u]; e != -1; e = edge[e].next)
{
int v = edge[e].v, g = edge[e].g;
next.v = v, next.g = cur.g + g;
next.f = next.g + d[v];
Q.push(next);
}
}
return -1;
}
inline void read_case()
{
init();
while(m--)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
read_graph(u, v, w);
}
scanf("%d%d%d", &s, &e, &k);
}
void solve()
{
read_case();
spfa(e);
int ans = A_STAR(s, e, k);
printf("%d\n", ans);
}
int main()
{
while(~scanf("%d%d", &n, &m))
{
solve();
}
return 0;
}