WOJ 85 回家的路-第k短路径

题目

求一个有向图中的第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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值