BOJ 1504. 특정한 최단 경로
1. 문제설명
N
개의 정점과M
개의 간선으로 이뤄진 그래프가 있다.- 경유지
v1
,v2
가 주어진다. - 1번 정점에서 N번 정점으로 이동하는데,
v1
,v2
를 반드시 거쳐야 한다. -
위 조건을 만족하는 최단 경로를 구하라
- 문제 분류
- Graph, Dijkstra
2. 알고리즘 설계
- 다익스트라 문제이고, 이전 문제와 달리 두 개의 노드를 반드시 들려야 한다.
- 우선 문제에서 방향성이 없는 그래프 라고 명시했으니, 입력
u, v
에 대해[u][v] = [v][u]
모두 저장해줘야 한다. - 이 문제의 경우 두 가지 경우의 수가 있을 것이다.
- 1->a->b->N
- 1->b->a->N
- 두 가지 경로에 대한 다익스트라 값을 구해서 최소값을 취하면 된다.
- 경로는 int 범위를 넘어설 수 있으니,
long long
을 취해야 한다. - 경로가 없는 경우 -1을 출력하라고 명시되어 있다.
- 경로가 더해지면 INF 값이 두번 이상 더해질 수 있으니, ‘INF 값보다 크다면’으로 조건을 세워야 한다.
3. 전체 코드
#include <bits/stdc++.h>
using namespace std;
using pii = pair<int,int>;
const int SZ = 802, INF = 0x3f3f3f3f;
int n, m, a, b;
vector<pii> adj[SZ];
long long solve(int src, int dst) {
int D[SZ];
fill(D, D+n+1, INF);
priority_queue<pii, vector<pii>, greater<pii>> pq;
pq.push({0, src});
D[src] = 0;
for(int u, v, w, dw; !pq.empty();) {
tie(w, u) = pq.top();
pq.pop();
for(auto nxt : adj[u]) {
tie(dw, v) = nxt;
if(dw + w < D[v]) {
D[v] = dw + w;
pq.push({dw+w, v});
}
}
}
return D[dst];
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> m;
for(int u, v, c; m--;) {
cin >> u >> v >> c;
adj[u].push_back({c, v});
adj[v].push_back({c, u});
}
cin >> a >> b;
long long tmp = min(solve(1,a) + solve(a,b) + solve(b,n), solve(1,b) + solve(b,a) + solve(a,n));
cout << (tmp >= INF ? -1 : tmp);
return 0;
}