티스토리 뷰

알고리즘/백준

백준 1240 노드사이의 거리 C++

4567은 소수 2023. 11. 20. 01:07

 

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

 

1240번: 노드사이의 거리

첫째 줄에 노드의 개수 $N$과 거리를 알고 싶은 노드 쌍의 개수 $M$이 입력되고 다음 $N-1$개의 줄에 트리 상에 연결된 두 점과 거리를 입력받는다. 그 다음 줄에는 거리를 알고 싶은 $M$개의 노드 쌍

www.acmicpc.net

처음에 문제를 보고 엣지 길이가 항상 1일거라 생각하고 예제를 봤는데 도저히 나올 수 없는 트리 구조여서 어떻게 하나 막막했던 문제였습니다. (하지만 문제를 다시 읽어보니 엣지 가중치가 있었다.....)

 

1000개 노드를 대상으로 탐색을 진행하고, 1000개 쿼리가 발생할 수 있으므로 그냥 다익스트라로 접근해도 뭔가 풀릴 거 같지만, 안전하게 우선순위 큐를 이용한 다익스트라로 문제를 풀었습니다. 

 

방식은 간단합니다. 입력으로 주어진 노드를 대상으로 그래프를 그리고 다익스트라 알고리즘 + 우선순위 큐 이용한 방식으로 해결하면 노드 사이의 거리를 구할 수 있습니다. 

 

다익스트라 알고리즘을 진행하면서 최단거리 갱신을 우선순위 큐를 이용해 진행하므로 O(N log N) (트리니까 엣지 전체 개수 = 노드 개수 - 1이고 노드 개수 N개 잡았을 때)에 해결할 수 있습니다. 그리고 쿼리도 M개 진행되므로 총 O(NM log N)에 해결할 수 있습니다.

 

코드는 다음과 같습니다.

#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <cstring>

using namespace std;

int n, m;
vector<pair<int, int>> vec[1001]; // {연결된 노드, 가중치}
int dist[1001]; // 거리 최대 1000만

void init()
{
    cin >> n >> m;
    int f, t, w; // from, to, weight
    for(int i = 0; i < (n-1); i++) {
        cin >> f >> t >> w;
        vec[f].push_back({t, w});
        vec[t].push_back({f, w});
    }
}

void dist_clear()
{
    for(int i = 0; i < 1001; i++) {
        dist[i] = 987654321;
    }
}

void dijkstra(int start, int last)
{
    // 우선순위 큐 이용한 다익스트라
    dist[start] = 0;
    
    // {현재까지 거리, 현재 탐색 노드}
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>> > pq; 
    pq.push({0, start});
    
    while(!pq.empty()) {
        int d = pq.top().first;
        int cur = pq.top().second;
        pq.pop();
        
        // 계산했던 값이 더 작은 경우 (더 안 해도 됨)
        if(dist[cur] < d)
            continue;
            
        // 탐색 
        for(auto v : vec[cur]){
            int next = v.first;
            int nd = v.second + d;
            
            // 갱신
            if(dist[next] > nd) {
                dist[next] = nd;
                pq.push({nd, next});
            }
        }
    }
    
    cout << dist[last] << '\n';
}

int main()
{
    ios_base :: sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    
    init();
    
    int start, last;
    for(int i = 0; i < m; i++) {
        dist_clear();
        cin >> start >> last;
        dijkstra(start, last);
    }
}

'알고리즘 > 백준' 카테고리의 다른 글

백준 12781 PIZZA ALVOLOC C++  (0) 2023.12.22
백준 1111 IQ Test C++  (0) 2023.12.16
백준 17136 색종이 붙이기 C++  (0) 2023.11.06
백준 9250 문자열 집합 판별 C++  (0) 2023.10.01
백준 11585 속타는 저녁 메뉴 C++  (0) 2023.09.30
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함