발상 & 풀이
문제를 읽어보면 매우 매우 전형적인 Dijkstra 문제라는 걸 알 수 있다. 사실 BFS 최단거리 문제들은 모두 Dijkstra 알고리즘을 기본 베이스로 한다. 지금까지의 문제들과 마찬가지로 현재 정점에 방문하기 이전의 정점을 기록하는 것으로 역추적할 수 있다.
코드
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
struct eg {
int s, e, v, cnt, p;
};
struct cmp {
bool operator() (eg a, eg b) {
return a.v > b.v;
}
};
void printpath(int c, vector<eg>& dp) {
if (dp[c].p == -1) {
cout << c << " ";
return;
}
printpath(dp[c].p, dp);
cout << c << " ";
}
int main()
{
int n, m; cin >> n >> m; vector<vector<eg>> arr(n + 1); vector<eg> dp(n + 1, { -1, -1, (int)21e8, -1, -1 });
for (int i = 1; i <= m; i++) {
int s, e, v; cin >> s >> e >> v;
arr[s].push_back({ s, e, v, -1, -1 });
}
int s, e; cin >> s >> e;
priority_queue<eg, vector<eg>, cmp> pq; pq.push({ s, s, 0, 1, -1 });
dp[s] = { s, s, 0, -1, -1 };
while (!pq.empty()) {
auto cur = pq.top(); pq.pop();
if (cur.s == e) {
cout << cur.v << "\n" << cur.cnt << "\n";
printpath(cur.s, dp);
return 0;
}
for (auto nx : arr[cur.s]) {
if (dp[nx.e].v > cur.v + nx.v) {
dp[nx.e].v = cur.v + nx.v;
dp[nx.e].cnt = cur.cnt + 1;
dp[nx.e].p = cur.s;
pq.push({ nx.e, nx.e, cur.v + nx.v, cur.cnt + 1, cur.s });
}
}
}
return 0;
}