[적용한 알고리즘]

다익스트라

 

[아이디어]

dist 배열을 최단경로를 저장하는 곳이 아닌,

k 개의 '최단경로들' 을 저장하는 용도로 사용한다.

(Heap 을 이용해서)

 

따라서 dist[i].top() 은 출발점에서 i 로 가는 k 번째 최단경로이다.

그래서 기존의 다익스트라에서 최단경로를 저장하는 부분을 살짝 손봐줘야하는데,

 

dist[nxt].size() < K 이거나 dist[nxt].top() > (현재 정점까지 k 번째 최단경로) + cost 라면,

dist[nxt] 에 ((현재 정점까지 k 번째 최단경로) + cost) push,

원래의 우선순위 큐에는 {(현재 정점까지 k 번째 최단경로) + cost, 다음 정점) 을 push 해주면 되겠다.

그리고 만약 size() 가 k 였다면, 하나를 당연히 pop 해줘야한다.

 

끝까지 돌았을 때 경로의 수가 k 개가 안된다면, 그 경로가 없는 것이므로 -1

있다면 top 을 출력하면 된다.

 

[교훈]

개 어 렵..

 

<코드>

#include <cstdio>
#include <queue>
using namespace std;
typedef pair<int, int> P;
const int MAX_V = 10001;
int N, M, K;

int main(){
    scanf("%d %d %d", &N, &M, &K);
    vector<pair<int, int>> adj[MAX_V];

    for (int i = 0; i < M; i++){
        int from, to, cost;
        scanf("%d %d %d", &from, &to, &cost);
        adj[from].push_back({to, cost});
    }

    priority_queue<int> dist[MAX_V];
    priority_queue<P, vector<P>, greater<P>> PQ;
    dist[1].push(0);
    PQ.push({0, 1});

    while (!PQ.empty()){
        auto p = PQ.top();
        PQ.pop();

        int cur = p.second;
        int dist_cur = p.first;
        
        for (auto q : adj[cur]){
            int nxt = q.first;
            int cost = q.second;

            if (dist[nxt].size() < K || dist[nxt].top() > dist_cur + cost){
                if (dist[nxt].size() == K){
                    dist[nxt].pop();
                }
                dist[nxt].push(dist_cur + cost);
                PQ.push({dist_cur + cost, nxt});
            }
        }
    }

    for (int i = 1; i <= N; i++){
        if (dist[i].size() != K){
            printf("-1\n");
        }
        else {
            printf("%d\n", dist[i].top());
        }
    }
    return 0;
}

'Algorithm > BOJ' 카테고리의 다른 글

[백준] 1647번 도시 분할 계획  (0) 2020.02.03
[백준] 1613번 역사  (0) 2020.02.01
[백준] 1507번 궁금한 민호  (0) 2020.02.01
[백준] 1956번 운동  (0) 2020.02.01
[백준] 1412번 일방통행  (124) 2020.02.01

+ Recent posts