Algorithm (PS)

[백준] 1956번: 운동 Python (플로이드-워셜)

minjiwoo 2023. 3. 4. 12:20
728x90

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

 

1956번: 운동

첫째 줄에 V와 E가 빈칸을 사이에 두고 주어진다. (2 ≤ V ≤ 400, 0 ≤ E ≤ V(V-1)) 다음 E개의 줄에는 각각 세 개의 정수 a, b, c가 주어진다. a번 마을에서 b번 마을로 가는 거리가 c인 도로가 있다는 의

www.acmicpc.net

pypy 로 제출해서 맞은 코드 

플로이드워셜이라는 힌트를 가지고 풀었다. 
처음에는 Union-find 로 사이클을 찾아야 하는가? 라고 생각했으나, 결국 문제에서는 최소 경로 비용을 구하는 것이 핵심이므로 플로이드 워셜로 푸는것이 더 적절하다고 판단했다. 

우선,graph 구성했다.  예제를 기준으로 아래의 graph를 만들어 보았다.
graph 에는 a-> b 가는 경로의 비용을 저장한다. 자기자신 노드에서 자기자신노드로 가는 경우 0 으로 초기화한다. 갈 수 없는 경로의경우 INF 값을 저장해서 경로가 없음을 표시했다. 

우선 플로이드 워셜 알고리즘으로 i -> j 지점까지의 최소 경로를 구해서 graph 에 저장했다. 

for k in range(1, v+1):
    for i in range(1, v+1):
        for j in range(1, v+1):
            if graph[i][k] + graph[k][j] < graph[i][j]:
                graph[i][j] = min(graph[i][k] + graph[k][j], graph[i][j])

graph 테이블에 저장한 최소경로를 이용해서 cycle이 생성되는 경우를 찾아주었다.

단, i == j == k 의 경우 자기자신 노드 to 자기자신 노드 가 되어버리므로 이 경우를 제외시켰다.
그리고 i to k 또는 k to j, j  to k 또는 k to i 경로 비용이 INF라는 것은 갈 수 없다는 것을 의미하므로 이 경우도걸러주었다. 

for k in range(1, v+1):
    for i in range(1, v+1):
        for j in range(1, v+1):
            if not (i == j == k):
                if graph[i][k] != INF and graph[k][j] != INF and graph[j][k] != INF and graph[k][i] != INF:
                    temp = graph[i][k] + graph[k][j] + graph[j][k] + graph[k][i]
                    answer = min(temp, answer)

 

전체 코드 

import sys

input = sys.stdin.readline

INF = int(1e9)
v, e = map(int, input().split())
answer = INF

graph = [[INF] * (v+1) for _ in range(v+1)]

for i in range(1, v+1):
    for j in range(1, v+1):
        if i == j:
            graph[i][j] = 0 # 자기 자신 to 자기 자신

for i in range(e):
    a, b, cost = map(int, input().split())
    graph[a][b] = cost

for k in range(1, v+1):
    for i in range(1, v+1):
        for j in range(1, v+1):
            if graph[i][k] + graph[k][j] < graph[i][j]:
                graph[i][j] = min(graph[i][k] + graph[k][j], graph[i][j])

for k in range(1, v+1):
    for i in range(1, v+1):
        for j in range(1, v+1):
            if not (i == j == k):
                if graph[i][k] != INF and graph[k][j] != INF and graph[j][k] != INF and graph[k][i] != INF:
                    temp = graph[i][k] + graph[k][j] + graph[j][k] + graph[k][i]
                    answer = min(temp, answer)
                    
if answer == INF:
    print(-1)
else:
    print(answer)
728x90