Problem Solving/BOJ

[백준 1504번] [Dijkstra] 특정한 최단 경로

  • -
728x90
반응형

최단 경로의 길이를 물어보는 것에서 다익스트라 문제임을 쉽게 파악할 수 있다.

 

이 문제에서 눈여겨 봐야할 지점은 반드시 거쳐야하는 정점이 있다는 것이다.

잠시 기억을 더듬어서 고등학교 경우의 수 문제에서 최단거리를 구할 때, 특정한 지점을 반드시 지나는 문제를 어떻게 풀었는지를 잘 생각해보자. 아마도 특정한 지점을 기준으로 분할해서 풀었던 기억이 있을 것이다.

 

마찬가지로 위 문제도 특정한 지점을 기준으로 분할해서 풀어주면 된다.

두 정점을 순서대로 v1, v2라고 하고, d(a, b)를 a부터 b까지 가는데 필요한 최단 경로의 길이라고 정의하자

 

d(1, N) = min(d(1, v1) + d(v1, v2) + d(v2, N), d(1, v2) + d(v2, v1) + d(v1, N))이다.

 

이를 보장할 수 있는 이유는 한번 이동했던 간선 및 정점을 다시 방문할 수 있으므로 각각의 경로는 독립적이기 때문이다.

따라서 그리디하게 각 정점까지의 최단 경로를 더해주는 것으로 정답을 도출할 수 있게 된다.

#include <bits/stdc++.h> #define fastio cin.tie(0)->sync_with_stdio(0) using namespace std; typedef pair<int, int> pii; typedef unsigned long long ull; typedef long long ll; typedef vector <ull> ullv1; typedef vector <vector <ull> > ullv2; const int INF = 987654321; int main() { fastio; int n, e; cin >> n >> e; vector<pii> edge[800]; for(int i = 0; i < e; i++){ int a, b, c; cin >> a >> b >> c; edge[a - 1].push_back({b - 1 , c}); edge[b - 1].push_back({a - 1, c}); } int v1, v2; cin >> v1 >> v2; v1--; v2--; tuple<int, int, int> check[3] = {{0, v1, v2}, {v1, v2, n - 1}, {v2, v1, n - 1}}; int result[3][2]; for(int i = 0; i < 3; i++){ int s, to_1, to_2; tie(s, to_1, to_2) = check[i]; int dist[800]; bool visited[800]; memset(visited, 0, sizeof(visited)); fill(dist, dist + 800, INF); dist[s] = 0; priority_queue<pii, vector<pii>, greater<pii> >pq; pq.push({0, s}); while(!pq.empty()){ int cur = -1; while(!pq.empty()){ if(!visited[pq.top().second]){ cur = pq.top().second; pq.pop(); break; } pq.pop(); } if(cur == -1) break; visited[cur] = 1; for(auto p : edge[cur]){ int to = p.first, cost = p.second; if(dist[cur] + cost < dist[to]){ dist[to] = dist[cur] + cost; pq.push({dist[to], to}); } } } result[i][0] = dist[to_1]; result[i][1] = dist[to_2]; } for(int i = 0; i < 3; i++){ for(int j = 0; j < 2; j++){ if(result[i][j] == INF){ cout << -1 << "\n"; return 0; } } } cout << min(result[0][0] + result[1][0] + result[2][1], result[0][1] + result[1][1] + result[2][0]) << "\n"; return 0; }

 

반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.