본문 바로가기
코딩/백준-파이썬

백준 1719번: 택배

by 철없는민물장어 2022. 7. 29.
728x90
반응형

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

 

1719번: 택배

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

www.acmicpc.net

문제

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

예시된 그래프에서 굵게 표시된 1, 2, 3, 4, 5, 6은 집하장을 나타낸다. 정점간의 간선은 두 집하장간에 화물 이동이 가능함을 나타내며, 가중치는 이동에 걸리는 시간이다. 이로부터 얻어내야 하는 경로표는 다음과 같다.

경로표는 한 집하장에서 다른 집하장으로 최단경로로 화물을 이동시키기 위해 가장 먼저 거쳐야 하는 집하장을 나타낸 것이다. 예를 들어 4행 5열의 6은 4번 집하장에서 5번 집하장으로 최단 경로를 통해 가기 위해서는 제일 먼저 6번 집하장으로 이동해야 한다는 의미이다.

이와 같은 경로표를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 두 수 n과 m이 빈 칸을 사이에 두고 순서대로 주어진다. n은 집하장의 개수로 200이하의 자연수, m은 집하장간 경로의 개수로 10000이하의 자연수이다. 이어서 한 줄에 하나씩 집하장간 경로가 주어지는데, 두 집하장의 번호와 그 사이를 오가는데 필요한 시간이 순서대로 주어진다. 집하장의 번호들과 경로의 소요시간은 모두 1000이하의 자연수이다.

출력

예시된 것과 같은 형식의 경로표를 출력한다.

 


모든경로를 알아야해서 플로이드워셜을 써볼까 했는데..

플로이드워셜로 했을 때 경로를 구할 방법이 생각이 안났다

그래서 다익스트라를 이용하고, 이걸 모든 집하장에 관하여 반복하는 식으로 했다

 

import sys, heapq
input=sys.stdin.readline

n,m=map(int,input().split()) #집하장개수n, 경로개수m


graph=[[]for _ in range(n+1)]

INF=int(1e9)
distance=[INF]*(n+1)
for i in range(m):
    a,b,c=map(int,input().split())
    graph[a].append((b,c))
    graph[b].append((a,c))

path=[[]for i in range(n+1)]
def dijkstra(start):
    q=[]
    heapq.heappush(q,(0,start))
    distance[start]=0
    while q:
        dist,now=heapq.heappop(q)
        if dist > distance[now]:
            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]))
                path[i[0]]=[]
                for p in path[now]:
                    path[i[0]].append(p)
                path[i[0]].append(i[0])


result=[[INF]*(n+1)for i in range(n+1)]
for i in range(1,n+1):
    dijkstra(i)
    for j in range(1,n+1):
        if i==j:
            result[i][j]=-1
        else:
            result[i][j]=path[j][0]
    path=[[]for i in range(n+1)] #path초기화
    distance=[INF]*(n+1) #거리초기화


for i in range(1,n+1):
    for j in range(1,n+1):
        if result[i][j]==-1:
            print("-",end=' ')
        else:
            print(result[i][j],end=' ')
    print()

우선 최단거리와 경로를 찾는 다익스트라 함수를 만든다

path[a]에는 a지점까지의 최단 경로가 리스트 형태로 들어가도록 했다

 

이후에, i가 1부터 n+1까지 증가하는 반복문 안에서 dijkstra(i)를 실행시킨다

그럼 시작지점이 i인 경우에 대하여 모든 지점으로의 최단 경로가 path 리스트에 들어간다.

이 path리스트를 가지고 처음 방문하는 집하장 번호를 result에 기록한다(result[i][j]=path[i][0])

 

 

이 과정을 모든 i에 관해 반복하면 result에는 처음 방문해야하는 집하장 번호가 전부 기록이 되고... 이 result를 양식에 맞게 출력하면 된다

728x90
반응형

'코딩 > 백준-파이썬' 카테고리의 다른 글

백준 1504번: 특정한 최단 경로  (0) 2022.07.30
백준 9012번: DSLR  (0) 2022.07.29
백준 117791번: 최소비용 구하기2  (0) 2022.07.29
백준 5014번: 스타트링크  (0) 2022.07.28
백준 5972번: 택배 배송  (0) 2022.07.27

댓글