求最K短路。
A星+SPFA。
其实A星算法的思想挺容易理解的。
关键在于优先队列的使用和 SPFA预处理将要走的路径长度。
保证每次选择一条最短路径来走。
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <iostream>
#include <cstdlib>
using namespace std;
const int maxn = 1005;
const int maxm = 500010;
const int INF = 1000000000;
struct Edge{
int v, next, w;
}edge[maxm], reedge[maxm];
int g[maxn], rg[maxn];
int dist[maxn];
int vis[maxn];
int n, e, m;
int src, des, k;
queue <int> que;
void addedge(int u, int v, int w){
e++;
edge[e].v = v;
edge[e].next = g[u];
edge[e].w = w;
g[u] = e;
reedge[e].v = u;
reedge[e].next = rg[v];
reedge[e].w = w;
rg[v] = e;
}
void spfa(){
int i;
for(i = 0; i <= n; i++) dist[i] = INF;
while(!que.empty()) que.pop();
memset(vis, 0, sizeof(vis));
que.push(des);
dist[des] = 0;
while(!que.empty()){
int u = que.front();
que.pop();
vis[u] = 0;
for(i = rg[u]; i; i = reedge[i].next){
int v = reedge[i].v;
if(dist[v] > reedge[i].w + dist[u]){
dist[v] = reedge[i].w + dist[u];
if(!vis[v]) que.push(v);
vis[v] = 1;
}
}
}
} //从终点到源点构造每一个点到终点的最短径
struct A{
int f, g, u;
bool operator < (const A &tmp) const {
if(tmp.f == f)return tmp.g < g;
return tmp.f < f;
}
};
//g为走到u点所经过的距离。
//f = g + dist[u] 表示从u点到终点的最短距离。
//用优先队列来维护使得每次选择的路径都是当前最短的,直到走到第k短路。
//特别当src = des时,由于这条路不能为0,因而k要加1。
priority_queue< A> pq;
int aStar(){
int cnt = 0;
if(des == src) k++;
if(dist[des] == INF) return -1;
A t, tt;
t.g = 0;
t.f = t.g + dist[src];
t.u =des;
while(!pq.empty()) pq.pop();
pq.push(t);
while(!pq.empty()){
t = pq.top();
pq.pop();
if(t.u == src){
cnt ++;
if(cnt == k) return t.g;
}
for(int i = g[t.u]; i; i = edge[i].next){
int v = edge[i].v;
tt.u = v;
tt.g = t.g + edge[i].w;
tt.f = tt.g + dist[v];
pq.push(tt);
}
}
return -1;
}
void init(){
memset(g, 0, sizeof(g));
memset(rg, 0, sizeof(rg));
e = 0;
}
int main(){
while(~scanf("%d%d",&n, &m)){
init();
int i;
int u, v, w;
for(i = 0; i < m; i++){
scanf("%d%d%d", &u, &v, &w);
addedge(u, v, w);
}
scanf("%d%d%d", &src, &des, &k);
spfa();
printf("%d\n", aStar());
}
return 0;
}