알고리즘/BAEKJOON (Python)

[ 백준 / 골드3 / 파이썬 Python ] 1719번 - 택배

Heeto 2023. 4. 10. 20:03
링크 : https://www.acmicpc.net/problem/1719
 

1719번: 택배

명우기업은 2008년부터 택배 사업을 새로이 시작하기로 하였다. 우선 택배 화물을 모아서 처리하는 집하장을 몇 개 마련했지만, 택배 화물이 각 집하장들 사이를 오갈 때 어떤 경로를 거쳐야 하

www.acmicpc.net

 

코드


n,m = map(int,input().split())
graph = [[1e9]*(n+1) for _ in range(n+1)]
dp = [[str(x)]*(n+1) for x in range(n+1)]

for _ in range(m):
    a,b,c = map(int,input().split())
    graph[a][b] = c
    graph[b][a] = c
    dp[a][b] = b
    dp[b][a] = a

for k in range(1,n+1):
    for i in range(1,n+1):
        for j in range(1,n+1):
            if graph[i][j] > graph[i][k]+graph[k][j]:
                graph[i][j] = graph[i][k]+graph[k][j]
                dp[i][j] = dp[i][k]

for i in range(1,n+1):
    dp[i][i] = "-"

for x in dp[1:]:
    print(*x[1:])

 

풀이


한 점에서 다른 점까지 최단경로로 이동할 때, 그 경로의 첫 번째 방문노드를 출력하는 문제이다.

처음에는 최단경로자체를 저장한 후에 가장 첫 노드만 따로 빼서 출력했는데 이상하게 8%에서 틀려서 첫 노드만 저장하는 것으로 바꾸었다.

 

모든 점에서 모든 노드로의 최단 경로를 찾아야 하므로 "플로이드 워샬" 알고리즘을 사용했다.

n이 200까지 올라가므로 시간복잡도는 O(n*3 = 800만)으로 2초안에 충분히 해결가능하다. 평소의 플로이드 워샬처럼 진행하나 dp테이블 하나가 추가된다. dp[x][y]는 x에서 y까지의 최단경로에서의 첫번째 방문노드를 의미한다.

a와 b가 연결되고 c라는 가중치가 있다. 입력까지만 놓고 본다면 a에서 b까지의 최단경로는 a-b이고 첫번째원소는 b이다.

이런 방식으로 들어오는 간선에 대한 정보를 모두 저장한다.

 

이제 플로이드 워샬의 방식대로 최단경로를 구하는데 탐색하다 만약 x->y의 경로가 최단경로로 갱신된다면 dp[x][y]는 dp[x][k]로 바꾸어 준다. 왜냐하면 x->y로 가는 최단경로는 x->k->y와 같고 따라서 x->k의 경로의 첫 번째 원소와 x->y의 첫 번째 원소가 같기 때문이다.