K번째 최단경로 찾기
포스트
취소

K번째 최단경로 찾기

K번째 최단경로 찾기

접근방법

heapq와 Dijkstra 알고리즘을 이용하였다

heapq(우선순위 큐)에 대하여 알아보자면,

모든 부모 노드가 자식보다 작거나 같은 값을 갖는 이진 트리이다.

파이썬 에서는 heappush 를 사용하여 큐에 push 할 수 있고,

heappop 을 사용하여 루트노드를 pop 할 수 있다.

다음과 같이 리스트로 넣는다면 첫번째 인덱스가 비교된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
import heapq

q = []

heapq.heappush(q, [1, 99])
heapq.heappush(q, [3, 1])
heapq.heappush(q, [2, 55])

print(q)

print(heapq.heappop(q))

print(q)
1
2
3
[[1, 99], [3, 1], [2, 55]]
[1, 99]
[[2, 55], [3, 1]]

하지만 우리는 최소 거리부터 K 번째를 구해야 하기 때문에, 다음과 같이 첫번째 인덱스(총 거리) 를 음수로 넣어줄 것이다.

1
2
3
4
5
6
7
8
9
import heapq

qq = []

heapq.heappush(qq, [-1, 99])
heapq.heappush(qq, [-3, 1])
heapq.heappush(qq, [-2, 55])

print(qq)
1
[[-3, 1], [-1, 99], [-2, 55]]

위의 방식대로 Dijkstra 알고리즘에 적용하여 코드를 풀어나가보자면,

해당 노드까지 가는 거리의 갯수가 k개보다 작다면

리스트에 바로 삽입을 해주고

k개 이상이라면

루트노드(가장 먼 거리) 를 팝 해준후에 삽입을 해주면 총 경로 개수가 k개로 유지가 된다

이후 결과출력때 거리가 k개 라면 바로 프린트 해주고, k개가 되지 않는다면 -1을 프린트 해주면 된다.

코드

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
29
30
31
32
33
34
# 1854 / K변째 최단경로 찾기
# https://www.acmicpc.net/problem/1854
import sys
import heapq
input = sys.stdin.readline

n, m, k = map(int, input().split())
arr =[[] for _ in range(n + 1)]
for _ in range(m):
    a, b, c = map(int, input().split())
    arr[a].append([b, c])

result = [[] for _ in range(n + 1)]
result[1].append(0)
q = [[0, 1]]

while q:
    cost, node = heapq.heappop(q)

    for next, w in arr[node]:
        dis = cost + w
        if len(result[next]) < k:
            heapq.heappush(result[next], -dis)
            heapq.heappush(q, [dis, next])
        elif dis < -result[next][0]:
            heapq.heappop(result[next])
            heapq.heappush(result[next], -dis)
            heapq.heappush(q, [dis, next])

for idx in range(1, n + 1):
    if len(result[idx]) < k:
        print(-1)
    else:
        print(-result[idx][0])

#

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.