洛谷P2865 [USACO06NOV] Roadblocks G 题解 次短路

题目链接:https://www.luogu.com.cn/problem/P2865

题目大意:求严格次短路。

解题思路:

先 spfa 跑一遍反图(由于是无向图,所以反图和原图其实是一样的图),得到估计函数的确定精确值。

然后 A* 跑一遍,即可。

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 5005, inf = 1e9;

int n, m, dis[maxn];
bool inq[maxn];
struct Edge {
    int v, w;
};
vector<Edge> g[maxn];

void spfa() {
    fill(dis+1, dis+n, inf);
    dis[n] = 0;
    queue<int> que;
    que.push(n);
    while (!que.empty()) {
        int u = que.front();
        que.pop();
        inq[u] = false;
        for (auto &[v, w] : g[u]) {
            if (dis[v] > dis[u] + w) {
                dis[v] = dis[u] + w;
                if (!inq[v]) inq[v] = true, que.push(v);
            }
        }
    }
}

struct Node {
    int u, f;

    bool operator < (const Node &o) const {
        return f + dis[u] > o.f + dis[o.u];
    }
};

int a_star() {
    int ans = inf;
    priority_queue<Node> que;
    que.push({1, 0});
    while (!que.empty()) {
        auto [u, f] = que.top();
        que.pop();
        if (u == n && f > dis[1]) {
            return f;
        }
        for (auto &[v, w] : g[u]) {
            if (f + w + dis[v] < ans)
                que.push({v, f + w});
        }
    }
    return -1;
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 0, u, v, w; i < m; i++) {
        scanf("%d%d%d", &u, &v, &w);
        g[u].push_back({v, w});
        g[v].push_back({u, w});
    }
    spfa();
    int ans = a_star();
    printf("%d\n", ans);
    return 0;
}
posted @ 2026-05-27 14:23  quanjun  阅读(11)  评论(0)    收藏  举报