所谓K短路,就是从s到t的第K短的路,第1短就是最短路。
1. 将图反向,用dijsktra求出t到所有点的最短距离,目的是求所有点到点t的最短路,用dis[i]表示i到t的最短路,其实这就是A*的启发函数,显然:h(n)<= n到t的实际代价。
2. 实现A*,f (x) = g(x) + h (x);定义估价函数。我们定义g(n)为从s到n所花费的代价,h(n)为dis[n],显然这符合A*算法的要求。
3. 初始化状态。状态中存放当前到达的点i, fi, gi。显然,fi = gi + dis[i]。初始状态为(S,dis[S],0),存入优先级队列中。
4. 状态转移。假设当前状态所在的点v相邻的点u,我们可以得到转换:(v, gv, d[v])-->(u, gu + cost[v][u], d[u])。
5. 终止条件。每个节点最多入队列K次,当t出队列K次时,即找到解。
/***********************************************
* Author: fisty
* Created Time: 2015/2/1 20:14:57
* File Name : poj2449.cpp
*********************************************** */
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <algorithm>
using namespace std;
#define Debug(x) cout << #x << " " << x <<endl
#define MAX_N 1100
const int INF = 0x3f3f3f3f;
typedef long long LL;
typedef pair<int, int> P;
int n, m;
int start, end, K;
//最短路
struct edge{
int to;
int cost;
edge(int _to, int _cost):to(_to), cost(_cost){}
};
vector<edge> _G[MAX_N];
int dist[MAX_N]; //终点到各点的最短路
void dijsktra(int t){
//t -> i
priority_queue <P, vector<P>, greater<P> > que;
memset(dist, 0x3f, sizeof(dist));
dist[t] = 0;
que.push(P(dist[t], t));
while(que.size()){
P q = que.top(); que.pop();
int v = q.second;
if(dist[v] < q.first) continue;
for(int i = 0;i < _G[v].size(); i++){
edge e = _G[v][i];
if(dist[e.to] > dist[v] + e.cost){
dist[e.to] = dist[v] + e.cost;
que.push(P(dist[e.to], e.to));
}
}
}
}
//Astar
struct node{
//定义了优先队列的结点
//f = g + h, f小的优先出队
int v;
int g; //g为节点start到i的实际值
int h; //h为节点i到end的最少估价值
node(int _v,int _g, int _h):v(_v), g(_g), h(_h){}
bool operator < (node a) const{
return h + g > a.h + a.g;
}
};
int cnt[MAX_N]; //节点的计数,若大于K则剪枝。因为是第K短,1个顶点不会超过K次
vector<edge> G[MAX_N];
int A_star(){
priority_queue <node> que;
memset(cnt, 0, sizeof(cnt));
que.push(node(start, 0, dist[start])); //入队的信息为 起点,起点的启发值, h值
while(que.size()){
node e = que.top(); que.pop();
int v = e.v, g = e.g, h = e.h;
cnt[v]++;
if(cnt[v] == K && v == end) return g ;
if(cnt[v] > K) continue;
for(int i = 0;i < G[v].size(); i++){
edge e = G[v][i];
que.push(node(e.to, e.cost + g, dist[e.to]));
}
}
return -1;
}
int main(){
//freopen("in.txt", "r", stdin);
cin.tie(0);
ios::sync_with_stdio(false);
cin >> n >> m;
for(int i = 0;i < m; i++){
int u, v, cost;
cin >> u >> v >> cost;
G[u].push_back(edge(v, cost));
_G[v].push_back(edge(u, cost));
}
cin >> start >> end >> K;
if(start == end){ //起点终点相同,最短路为0
++K;
}
dijsktra(end);
int ans = A_star();
if(ans == -1)
cout << -1 << endl;
else
cout << ans << endl;
return 0;
}