알고리즘 문제풀이

[백준 1916] 최소비용 구하기 (C++)

SiO2whocode 2024. 10. 23. 23:27
728x90

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

다익스트라

도시를 연결하는 단방향 버스 (출발점, 도착점, 비용)이 주어지고

임의의 출발점과 도착점이 주어졌을 때, 이 둘을 잇는 최소 비용을 출력하는 문제

 

접근방법 

음수인 비용이 없어서 다익스트라로 풀어도 된다. (벨만포드로 안풀어도 됨)

이거 풀다가 내가 다익스트라를 제대로 이해하고 있는게 맞나 의심했음..다시 공부해야 할 것 같다..

다익스트라 기본 개념은 임의의 출발점 하나에 대해 모든 노드에 대한 최소 거리를 저장하고 있는 1차원 배열이 하나 있고,

방문한 노드를 하나씩 추가해 가면서 이 배열을 갱신하는 방식이다.

 

이 문제를 풀 때는,

- 인접행렬 (각 노드에 대해 연결된 버스 노선을 담고 있는 2차원 배열. ex. 1번: {(2번도시, 비용2), (3번도시, 비용3), (4번도시, 비용4),,,} 이런식이다.)

- 출발점으로부터 각 노드의 최소거리를 저장하게 될 1차원 배열 (distance[])

- 노드의 방문여부를 저장한 1차원 배열 (visit[])

- 방문한 노드의 갯수 (visitedNode)

 

반복문을 돌면서 distance를 계속 갱신해줬는데, 이 반복문은 모든 노드를 방문할 때 까지만 반복한다.

그 안에서는 매번 distance가 최소이면서 아직 방문하지 않은 노드를 하나 선택해서, 그 노드(cur)에 방문한다.

그 노드에 방문한다는 건, 그 노드에서 출발해서 갈 수 있는 버스를 탈 수 있다는 것과 같다.

따라서 cur에 연결된 버스를 인접행렬(adj)를 참고하여 모두 순회한다.

하나의 버스를 볼 때 마다, 그 버스의 도착점(next)에 대한 최소비용을 갱신한다.

따라서, 현재 가장 가까운 노드 하나를 추가하는데, 이때 그 노드와 직접적으로 연결되는 노드의 최소비용만 갱신하는 것

 

일단 이 문제는 이렇게만 풀어도 통과가 됐는데, 다익스트라 풀이하는 다른 풀이들을 봐보니 간선하나에 대한 도착노드만 보는 것 같지가 않아서 다시 공부해봐야겠다고 느꼈음. 

 

오답노트

첨에 양방향인줄..단방향이었다..그리고 가장 가까운 노드를 찾을 때 min 값으로 22222로 대충 설정해뒀더니 안됐다.

987654321이걸로 고쳤더니 됐음. 아우 너무 헷갈려!!

 

소스코드

#include <iostream>
#include <vector>

using namespace std;
int INF = 987654321;

int main(){
    
    // input
    int N, M;
    cin >> N >> M;
    
    vector<vector<pair<int, int>>> adj(N+1);
    int s, e, c;
    for(int i = 1; i <= M ; i++){
        cin >> s >> e >> c;
        adj[s].push_back(make_pair(e, c)); // 단방향이었음!
    }
    
    vector<int> distance(N+1, INF);
    
    int S, E;
    cin >> S >> E;
    
    distance[S] = 0;
    
    // process
    vector<bool> visit(N+1, false);
    int visitedNode = 1;
    
    while(visitedNode < N){
        int cur = 1;
        // 방문하지 않은 노드 중 가장 가까운 노드 선정
        int min = INF;
        for(int i = 1; i <= N ; i++){
            if(!visit[i] && min >= distance[i]){
                min = distance[i];
                cur = i;
            }
        }
        visit[cur] = true;
        visitedNode++;
        
        for(int i = 0; i < adj[cur].size() ; i++){
            int next = adj[cur][i].first;
            int next_cost = adj[cur][i].second;
            // 간선 사용하여 거리 갱신
            if(distance[next] > distance[cur] + next_cost){
                distance[next] = distance[cur] + next_cost;
            }
        }
    }
    
    cout << distance[E];
    
}
728x90