Files
python/TangDou/AcWing/AStar/178_AStar_Struct.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

105 lines
2.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1010;
const int M = 200010;
int n, m;
int S, T, K;
int h[N], rh[N];
int e[M], w[M], ne[M], idx;
int dist[N];
bool st[N];
int cnt[N];
void add(int h[], int a, int b, int c) {
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
// 只有点号和距离时,按距离由小到大排序
struct N1 {
int u, d;
const bool operator<(const N1 &b) const {
return b.d < d; // 谁的距离短谁靠前
}
};
// 当有点号+距离+估值函数时,按估值函数值由小到大排序
struct N2 {
int u, d, f;
const bool operator<(const N2 &b) const {
return b.f < f;
}
};
// 经典的Dijkstra,计算终点到图中其它所有点的最短路径
void dijkstra() {
priority_queue<N1> q;
q.push({T, 0});
memset(dist, 0x3f, sizeof dist);
dist[T] = 0;
while (q.size()) {
N1 t = q.top();
q.pop();
int u = t.u;
if (st[u]) continue;
st[u] = true;
for (int i = rh[u]; ~i; i = ne[i]) {
int v = e[i];
if (dist[v] > dist[u] + w[i]) {
dist[v] = dist[u] + w[i];
q.push({v, dist[v]});
}
}
}
}
int astar() {
priority_queue<N2> q;
q.push({S, 0, dist[S]}); // 起点入队列
while (q.size()) {
int u = q.top().u;
int d = q.top().d;
q.pop();
cnt[u]++; // u出队一次
if (u == T && cnt[u] == K) return d; // 找到到终点的第K短路
for (int i = h[u]; ~i; i = ne[i]) {
int v = e[i];
if (dist[v] < INF) // 如果是无效借力点,跳过
q.push({v, d + w[i], d + w[i] + dist[v]}); // 点,距离,估值函数值
}
}
return -1;
}
int main() {
cin >> n >> m;
memset(h, -1, sizeof h);//正向图
memset(rh, -1, sizeof rh);//反向图
while (m--) {
int a, b, c;
cin >> a >> b >> c;
add(h, a, b, c); // 正向建图,常规逻辑
add(rh, b, a, c); // 反向建图,用于获取终点t到图中所有点的最短路径。为估值函数作准备
}
cin >> S >> T >> K;
// ① 如果起点与终点最开始是一样的,那么就需要入队列k+1次,这是一个坑
if (S == T) K++;
// ② 先跑一遍Dijkstra,方便计算出估值函数
dijkstra();
// ③ 利用Dijkstra计算出来的终点到任意点的值,再加上当前走过的距离,等于AStar的估值函数
cout << astar() << endl; // A*算法
return 0;
}