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

백준 문제 링크 : 1504번: 특정한 최단 경로 (acmicpc.net)

백준 1504번 문제 사진

문제 요약

입력 값 : n(정점 갯수), e(간선 갯수), a,b,c(간선 정보), v1,v2(반드시 지나야 하는 두 점)

  1. 시작점과 끝점은 반드시 1, n이다.
  2. 간선과 정점은 여러 번 사용할 수 있다.
  3. 반드시 지나야 하는 두 점이 있다.

문제 풀이 과정

이 문제를 한 줄로 요약하자면 입력된 두 정점을 반드시 지나는 1과 n 사이의 최단 경로의 길이를 출력하라는 말이 될 것 같습니다. 다만 간선이나 정점들을 중복하여 사용하는 것이 가능하기 때문에 최단 경로를 찾는데 제약이 많이 줄어들죠.

이 문제에서 반드시 지나야 하는 정점을 지나면서 시작점과 끝점을 이어주는 경우는 두 가지가 있습니다.

  1. v1이 n보다 1에 가까울 경우 [1 -> v1 -> v2 -> n]
  2. v1이 1보다 n에 가까울 경우 [1 -> v2 -> v1 -> n]

위 경로들의 길이 중 최솟값이 정답이 되죠. 이를 위해서 구해야 하는 값은 반드시 지나는 점들과 시작점, 끝점의 최단 경로의 길이 입니다.

이를 위해서 두 개의 정점을 입력 받고 해당 정점들 사이의 거리를 구해주는 함수를 만들어줘야 해요. 저는 distance_a2b라는 함수를 만든 후 최단 경로들을 구해 더해주는 방법을 사용했습니다.

#include <iostream>
#include <queue>
#include <vector>
#define MAX 1e8
using namespace std;
//입력 변수
int v,e;
int must_a,must_b;
//정점 벡터
vector<vector<pair<int,int>>> vertexes;
//거리 벡터
vector<int> vertex_distances;
//특정 정점 거리 연산 함수
int distance_a2b(int a,int b){
    vertex_distances = vector<int>(v+1,MAX);
    priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>  queue;
    vertex_distances[a] = 0;
    queue.push(pair<int,int>(0,a));
    while (!queue.empty()) {
        int cur_vertex = queue.top().second;
        int cur_cost = queue.top().first;
        queue.pop();
        if (vertex_distances[cur_vertex] < cur_cost) {
            continue;
        }
        for (int i = 0; i < vertexes[cur_vertex].size();i++) {
            int v_vertex = vertexes[cur_vertex][i].second;
            int v_distance = vertexes[cur_vertex][i].first + cur_cost;
            if (vertex_distances[v_vertex] > v_distance) {
                vertex_distances[v_vertex] = v_distance;
                queue.push({v_distance,v_vertex});
            }
        }
    }
    return vertex_distances[b];
}
int main()
{
    cin >> v >> e;
    vertexes = vector<vector<pair<int,int>>>(v + 1);
    for (int i = 0;i < e;i++) {
        int a,b,cost;
        cin >> a >> b >> cost ;
        vertexes[a].push_back({cost,b});
        vertexes[b].push_back({cost,a});
    }
    cin >> must_a >> must_b;
    //반드시 지나야 하는 정점 거리 연산
    int must_a2b = distance_a2b(must_a,must_b);
    //반드시 지나야하는 정점과 시작 끝 정점 계산
    int o2a = distance_a2b(1,must_a);
    int o2b = distance_a2b(1,must_b);
    int b2n = distance_a2b(must_b,v);
    int a2n = distance_a2b(must_a,v);
    //각각의 결과 합
    int result_case_1 =  o2a + must_a2b + b2n;
    int result_case_2 =  o2b + must_a2b + a2n;
    //합 중 최솟값 선별
    int result = min(result_case_1,result_case_2);
    //출력
    if (result >= MAX) {
        cout << -1 << endl;
    }
    else {
        cout << result << endl;
    }
    return 0;
}

다익스트라 알고리즘을 사용한 다른 문제의 경우 아래 카테고리에서 찾아보실 수 있습니다.

다익스트라 – PostiveGround

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

위로 스크롤