Baekjoon Review

[Gold 4] 1504 특정한 최단 경로

hanseongbugi 2024. 9. 20. 17:36

https://www.acmicpc.net/problem/1504

 

이 문제는 다익스트라 알고리즘을 활용한다.

 

다익스트라를 활용해서 무조건 거쳐야하는 정점까지의 최단 거리를 구한다.

이후 그 정점에서 부터 N까지의 최단 거리를 구하면 해결할 수 있다.

즉, 다익스트라 알고리즘을 3번 활용한다.

 

1번 정점에서부터 다익스트라 알고리즘을 활용하면

1번 정점애서부터 모든 정점에대한 최단 거리를 구할 수 있다.

따라서 1번 정점에서부터 u와 v정점까지의 최단 거리를 저장한다.

dijk(1);
int to_u = dist[u];
int to_v = dist[v];

 

1에서부터 u와 v정점까지의 최단 거리를 구했다면

u에서 N와 v 정점간의 최단 거리와 v에서 N간 최단 거리를 구한다.

v에서 u까지의 최단거리를 구하지 않는 이유는 양방향이기 때문

dijk(u);
int u_to_v = dist[v];
int u_to_N = dist[N];

dijk(v);
int v_to_N = dist[N];

 

이렇게 3번의 다익스트라를 통해 최단 거리를 구했다면

합을 통해 최종 결과를 만들어낸다.

int result;
result = min(INF, to_u + u_to_v + v_to_N);
result = min(result, to_v + u_to_v + u_to_N);
    
if(result >= INF)
    cout<<-1;
else
    cout<<result;

 

 

목적지가 C이고 각각의 정점을 A와 B라고 했을 때

다익스트라를 통해 1에서 A와 B까지의 최소 비용 경로를 구할 수 있다.

그후 A와 C까지의 거리와 B와 C까지의 최소 비용을 구한다.

마지막으로 1-A-C와 1-B-C 중 가장 적은 비용을 구하면 된다.

 

위 코드를 보면

첫번째 min함수는 1 - u - N 경로의 비용을 구하고 있다.

두번째 min함수는 1 - v - N 경로의 비용을 구하고 있다.

 

경로의 합 사이에 u와 v사이의 최소 비용을 더하여 u와 v를 반드시 거치도록 하였다.

 

 

#include <iostream>
#include <vector>
#include <queue>
using namespace std;
#define INF 200000000

int N, E, u, v;
vector<pair<int, int>> graph[801];
int dist[801];
bool visited[801];

void dijk(int st){
    // 1번에서 N번까지 이동
    // u와 v 정점을 반드시 거칠 것
    for(int i = 0;i<=N;i++)
        dist[i] = INF;

    priority_queue<pair<int, int>> pq;
    pq.push({0, st});
    dist[st] = 0;

    while(!pq.empty()){
        int cost = -pq.top().first;
        int now = pq.top().second;
        pq.pop();

        if(cost > dist[now])
            continue;

        for(int i = 0;i<graph[now].size();i++){
            int next = graph[now][i].first;
            int nCost = graph[now][i].second;

            if(dist[next] > nCost + cost){
                dist[next] = nCost + cost;
                pq.push({-dist[next], next});
            }
        }
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin>>N>>E;
    int a, b, c;
    for(int i = 0;i<E;i++){
        cin>>a>>b>>c;
        graph[a].push_back({b, c});
        graph[b].push_back({a, c});
    }
    cin>>u>>v;

    dijk(1);
    int to_u = dist[u];
    int to_v = dist[v];

    dijk(u);
    int u_to_v = dist[v];
    int u_to_N = dist[N];

    dijk(v);
    int v_to_N = dist[N];

    int result;
    result = min(INF, to_u + u_to_v + v_to_N);
    result = min(result, to_v + u_to_v + u_to_N);
    
    if(result >= INF)
        cout<<-1;
    else
        cout<<result;
}