题目分析
本题就是求k短路,其实自己也没有学过A*算法 f[x]=g[x]+h[x]
在本题中g[x]为估价函数,表示从x点达到目标点的距离,注意g[x],小于等于真实值,因此这样就可以用spfa跑一边最短路即可,至于h[x]表示到达当前点x的代价,很明显这个在运算的时候可以得到,这样就可以构建一个优先队列求解了。h[x]+g[x]小的先出队,并且用一个计数的计算出每个点被到达多少次。这样就可以得出结果了。
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1005;
const int maxm = 100005;
const int INF = 0x7f;
struct Node{
int h, g, u; //h代表当前搜索时的代价, g是一个估价函数(注意g一定要小于或者等于真实值)
Node(){}
Node(int a,int b,int c):h(a),g(b),u(c){}
bool operator < (const Node temp)const{ //重载小于运算符
return (h+g) > (temp.h+temp.g);
}
};
int head1[maxn], head2[maxn], g[maxn], vis[maxn], tot1, tot2;
struct Edge{
int to, w, next;
}e1[maxm], e2[maxm]; //正向和反向分别建边,反向建边主要是为了能求出估价函数g(spfa或者dijkstra都可)
void addedge(int from, int to, int w){
e1[tot1].to = to;
e1[tot1].w = w;
e1[tot1].next = head1[from];
head1[from] = tot1++;
e2[tot2].to = from;
e2[tot2].w = w;
e2[tot2].next = head2[to];
head2[to] = tot2++;
}
void spfa(int s){
memset(vis, 0, sizeof(vis));
memset(g, INF, sizeof(g));
queue <int> que;
g[s] = 0, vis[s] = 1;
que.push(s);
while(!que.empty()){
int u = que.front(); que.pop();
vis[u] = 0;
for(int i = head2[u]; i != -1; i = e2[i].next){
int v = e2[i].to, w = e2[i].w;
if(g[v] > g[u] + w){
g[v] = g[u] + w;
if(!vis[v]){
vis[v] = 1;
que.push(v);
}
}
}
}
}
void solve(int s, int t, int k){
memset(vis, 0, sizeof(vis));
if(s == t) k++; //注意这一点
priority_queue <Node> pq;
pq.push(Node(0, g[s], s));
while(!pq.empty()){
Node cur = pq.top(); pq.pop();
// printf("%d %d %d\n", cur.h, cur.g, cur.u);
vis[cur.u]++;
if(vis[cur.u] > k) continue;
if(vis[cur.u] == k && cur.u == t){
printf("%d\n", cur.h+cur.g);
return ;
}
for(int i = head1[cur.u] ; i != -1; i = e1[i].next){
int v = e1[i].to, w = e1[i].w;
pq.push(Node(w+cur.h, g[v], v));
}
}
printf("-1\n");
}
void init(){
tot1 = tot2 = 0;
memset(head1, -1, sizeof(head1));
memset(head2, -1, sizeof(head2));
}
int main(){
int N, M, S, T, K;
while(scanf("%d%d", &N, &M) != EOF){
init();
int from, to, w;
for(int i = 0; i < M; i++){
scanf("%d%d%d", &from, &to, &w);
addedge(from, to, w);
}
scanf("%d%d%d", &S, &T, &K);
spfa(T);
if(g[S] == INF){
printf("-1\n");
continue;
}
solve(S, T, K);
}
return 0;
}