这题题意为给一张有向图,还有起点s,终点e,求s到e的第k短的路。
思路:此题要用到A*算法,先求反向的从终点e到各个点的最短路径,定义结构体
struct node
{
int p,h,g;
bool operator <(const node a)const
{
return g+h<a.g+a.h;
}
}
即p为该点,h为从原点走到p的已花费代价,g为预估到终点的花费,即p到终点的最短路。
在bfs的过程中如果一个点被出队k次,即求出原点到该点的第k短路。
而且该题的主要目的是给大家一个较好的基于邻接表的dijstra优先队列实现算法。
代码如下:
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#include <cstring>
#include <iostream>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=1010;
int n,m,s,e,k;
int time[1010];
struct Edge {
int from, to, dist;
Edge(int u, int v, int d):from(u),to(v),dist(d) {}
};
struct HeapNode {
int d, u;
bool operator < (const HeapNode& rhs) const {
return d > rhs.d;}
};
struct node
{
int p,g,h;
bool operator <(const node &a) const
{
return g+h>a.g+a.h;
}
};
struct Dijkstra {
int n, m;
vector<Edge> edges;
vector<int> G[maxn];
bool done[maxn];
int d[maxn];
int p[maxn];
void init(int n) {
this->n = n;
for(int i = 0; i <= n; i++) G[i].clear();
edges.clear();
}
void AddEdge(int from, int to, int dist) {
edges.push_back(Edge(from, to, dist));
m = edges.size();
G[from].push_back(m-1);
}
void dijkstra(int s) {
priority_queue<HeapNode> Q;
for(int i = 1; i <= n; i++) d[i] = INF;
d[s] = 0;
memset(done, 0, sizeof(done));
Q.push((HeapNode){0, s});
while(!Q.empty()) {
HeapNode x = Q.top(); Q.pop();
int u = x.u;
if(done[u]) continue;
done[u] = true;
for(unsigned int i = 0; i < G[u].size(); i++) {
Edge& e = edges[G[u][i]];
if(d[e.to] > d[u] + e.dist) {
d[e.to] = d[u] + e.dist;
p[e.to] = G[u][i];
Q.push((HeapNode){d[e.to], e.to});
}
}
}
}
}dij,bd;
int bfs()
{
priority_queue<node> q;
node start;
start.p=s,start.h=0,start.g=0;
q.push(start);
int cost=-1;
while(!q.empty())
{
node temp=q.top();
q.pop();
time[temp.p]++;
if(time[temp.p]==k&&temp.p==e)
{
cost=temp.h+temp.g;
break;
}
if(time[temp.p]>k)
{
continue;
}
for(unsigned int i=0;i<bd.G[temp.p].size();i++)
{
node temp1;
temp1.p=bd.edges[bd.G[temp.p][i]].to;
temp1.h=bd.edges[bd.G[temp.p][i]].dist+temp.h;
temp1.g=dij.d[temp1.p];
q.push(temp1);
}
}
return cost;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(time,0,sizeof(time));
dij.init(n);
bd.init(n);
for(int i=0;i<m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
dij.AddEdge(v,u,w);
bd.AddEdge(u,v,w);
}
scanf("%d%d%d",&s,&e,&k);
dij.dijkstra(e);
if(s==e)
k++;
int cost=bfs();
cout<<cost<<endl;
}
}