题目
求一个有向图中的第k短路径(可以有环),输出第k短路径的长度
算法
先用Dijkstra求出从终点到起点的反向最短路径。(使用反向图)
再用A*算法,这篇博文有详细解释链接,代码参考了这位博主的写法(使用正图),还没有太理解,等我再参透一下。。
代码
#include<iostream>
#include <vector>
#include <queue>
using namespace std;
struct ANode{
int f, g, v;
ANode() = default;
bool operator<(const ANode b) const {
if (b.f == this->f) {
return b.g < this->g;
} else {
return b.f < this->f;
}
}
};
/**
* 第k短路径
* @return
*/
int main() {
int N, M, K;
while (cin >> N >> M >> K) {
// 有向图,
vector<vector<pair<int, int>>> graph(N+1, vector<pair<int,int>>());
vector<vector<pair<int, int>>> reGraph(N+1, vector<pair<int,int>>()); // 逆向索引
int from, to, cost;
for (int i = 0; i < M; ++i) {
cin >> from >> to >> cost;
graph[from].push_back({to, cost});
reGraph[to].push_back({from, cost});
}
vector<int> dist(N+1, 0x7fffffff);
vector<bool> visited(N+1, false);
// 小根堆,Dijkstra求出终点到各个点的最短距离
auto cmp = [](pair<int, int>& a, pair<int, int>& b) {
return a.second > b.second;
};
priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(cmp)> heap(cmp);
heap.push({N, 0});
dist[N] = 0;
while (!heap.empty()) {
int vertex = heap.top().first;
heap.pop();
if (visited[vertex]) {
continue;
}
visited[vertex] = true;
for (auto& node : reGraph[vertex]) {
// node是于vertex邻接的节点
if (!visited[node.first] && dist[node.first] > dist[vertex] + node.second) {
dist[node.first] = dist[vertex] + node.second;
heap.push({node.first, dist[node.first]});
}
}
}
// for (int i = 1; i < N + 1; ++i) {
// cout << N << " to " << i << " dist : " << dist[i] << endl;
// }
// A-star算法, 默认第一个节点为起点
int cnt = 0;
if (N == 1) {
K++;
}
if (dist[1] == 0x7fffffff) {
return -1;
}
ANode temp;
temp.v = 1;
temp.g = 0;
temp.f = temp.g + dist[1];
priority_queue<ANode> priorityQueue;
priorityQueue.push(temp);
while (!priorityQueue.empty()) {
ANode tempNode = priorityQueue.top();
priorityQueue.pop();
if (tempNode.v == N) {
cnt++;
if (cnt == K) {
cout << tempNode.g << endl;
break;
}
}
for (auto& nextNode : graph[tempNode.v]) {
temp.v = nextNode.first;
temp.g = tempNode.g + nextNode.second;
temp.f = temp.g + dist[nextNode.first];
priorityQueue.push(temp);
}
}
}
return 0;
}