(2022년 7월 14일 최초 작성)

그것이 플로이드 워샬 문제입니다.
문제의 기본 아이디어는 다음과 같습니다.
다른 곳을 지날 때 A에서 B로 직진하지 않고 A에서 B로 갈 때(K)
비용이 더 낮으면 인접 행렬을 해당 비용으로 업데이트합니다.
그러면 이런 표현이 나오죠
비용(A, B) = 최소(비용(A,B), 비용(A, K) + 비용(K, B))
따라서 삼중반복문으로 풀어야 할 문제이다.
각 지점에서 각 지점까지의 비용을 찾아야 하기 때문입니다.
시간 복잡도는 O(n^3)입니다.
import sys
input = sys.stdin.readline
INF = int(1e9)
n, m = int(input()), int(input())
graph = (((INF) * (n + 1)) for _ in range(n + 1))
for i 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):
if a == b:
graph(a)(b) = 0
else:
graph(a)(b) = min(graph(a)(b), graph(a)(k) + graph(k)(b))
for x in range(1, n + 1):
for y in range(1, n + 1):
if graph(x)(y) == INF:
print(0, end = ' ')
else:
print(graph(x)(y), end = ' ')
print()
==========================================
(리뷰 2023-03-04)
Floyd Warhall의 근본적인 문제인데, 문제는 공식처럼 기억해야 하는 알고리즘입니다.
시간복잡도는 O(N^3)이지만 조건에서 지정한 N의 범위가 작을 때는 최단 거리 문제를 푸는 것이 가장 편리하다.
이것은 어떤 지점에서 어떤 지점까지의 거리를 볼 수 있기 때문에 좋은 알고리즘입니다.
아래에서 해결!
import sys
input = sys.stdin.readline
INF = int(1e9)
n = int(input())
m = int(input())
graph = ((INF) * (n + 1) for _ in range(n + 1))
for _ in range(m):
a, b, c = map(int, input().split())
graph(a)(b) = min(graph(a)(b), c)
for i in range(1, n + 1):
graph(i)(i) = 0
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 x in range(1, n + 1):
for y in range(1, n + 1):
print(graph(x)(y) if graph(x)(y) != INF else 0, end = ' ')
print()
코드가 조금 더 깔끔한 느낌입니다.
