Algorithm/Dijkstra

[Python] 백준 1753번 최단경로

코딩쪼앙 2023. 3. 14. 21:43

문제

 

1753번: 최단경로

첫째 줄에 정점의 개수 V와 간선의 개수 E가 주어진다. (1 ≤ V ≤ 20,000, 1 ≤ E ≤ 300,000) 모든 정점에는 1부터 V까지 번호가 매겨져 있다고 가정한다. 둘째 줄에는 시작 정점의 번호 K(1 ≤ K ≤ V)가

www.acmicpc.net

입력

  • 첫째 줄에 정점의 개수 V와 간선의 개수 E가 주어진다. (1 ≤ V ≤ 20,000, 1 ≤ E ≤ 300,000) 모든 정점에는 1부터 V까지 번호가 매겨져 있다고 가정한다. 둘째 줄에는 시작 정점의 번호 K(1 ≤ K ≤ V)가 주어진다. 셋째 줄부터 E개의 줄에 걸쳐 각 간선을 나타내는 세 개의 정수 (u, v, w)가 순서대로 주어진다. 이는 u에서 v로 가는 가중치 w인 간선이 존재한다는 뜻이다. u와 v는 서로 다르며 w는 10 이하의 자연수이다. 서로 다른 두 정점 사이에 여러 개의 간선이 존재할 수도 있음에 유의한다.

출력

  • 첫째 줄부터 V개의 줄에 걸쳐, i번째 줄에 i번 정점으로의 최단 경로의 경로값을 출력한다. 시작점 자신은 0으로 출력하고, 경로가 존재하지 않는 경우에는 INF를 출력하면 된다.

입력 예제

5 6
1
5 1 1
1 2 2
1 3 3
2 3 4
2 4 5
3 4 6

출력 예제

0
2
3
7
INF

문제 풀이

  • 다익스트라 알고리즘 수행하여 출발노드로부터 모든 노드까지의 거리 탐색
  • 도달할 수 없다면 INF를 출력하고, 도달할 수 있다면 최단경로 출력

다익스트라 알고리즘을 사용한 코드

import heapq
import sys
input = sys.stdin.readline
INF = int(1e9)
n, m = map(int,input().split())
start = int(input())
graph = [[] for _ in range(n + 1)]
distance = [INF] * (n + 1)

# 간선 정보 입력받기
for _ in range(m):
    # 출발노드, 도착노드, 비용
    a,b,c = map(int,input().split())
    graph[a].append((b, c))


# 다익스트라 알고리즘 수행
def dijkstra(start):
    q = []
    # 거리, 노드
    heapq.heappush(q,(0, start))
    distance[start] = 0

    while q:
        dist, now = heapq.heappop(q)
        # 꺼낸 거리비용이 이미 저장된 값보다 크다면 무시
        if distance[now] < dist:
            continue
        # 거리값이 더 작다면 현재 노드와 연결된 모든 노드들 탐색
        for i in graph[now]:
            # 그래프 (노드, 비용)
            cost = dist + i[1]
            # 현재 거리를 거쳐가는 값이 더 작다면 거리값 갱신 후 힙에 삽입
            if cost < distance[i[0]]:
                distance[i[0]] = cost
                heapq.heappush(q,(cost, i[0]))

dijkstra(start)
for i in range(1, n + 1):
    if distance[i] == INF:
        print('INF')
    else:
        print(distance[i])

 

크루스칼 알고리즘을 사용한 코드

import sys
input = sys.stdin.readline
INF = int(1e9)
n, m = map(int,input().split())
start = int(input())
graph = [[INF] * (n + 1) for _ in range(n + 1)]

# 자기자신 거리는 0으로 초기화
for a in range(1, n + 1):
    for b in range(1, n + 1):
        if a == b:
            graph[a][b] = 0

# 간선정보 입력
for _ in range(m):
    a,b,c= map(int,input().split())
    if graph[a][b] > c:
        graph[a][b] = c

# 플로이드워셜 알고리즘 수행
for k in range(1, n + 1):
    for a in range(1, n + 1):
        for b in range(1, n + 1):
            graph[a][b] = min(graph[a][b], graph[a][k] + graph[k][b])


for i in range(1, n + 1):
    if graph[1][i] == INF:
        print('INF')
    else:
        print(graph[1][i])
  • 최대 입력 값이 300,000이라 그런지 크루스칼 알고리즘은 메모리 초과 판정을 받았다 
  • 입력 값이 많은 경우 다익스트라 알고리즘 사용하기 !