백준 11657번 - 타임머신

타임머신 문제 바로 가기

풀이 날짜: 2026-01-15

baekjoon 알고리즘 문제 풀이

풀이 코드


import sys
input = sys.stdin.readline

INF = int(1e9)

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

dist = [INF] * (n+1)
dist[1] = 0

for _ in range(n-1):
    updated = False
    for a,b,c in data:
        if dist[a] != INF and dist[b] > dist[a] + c:
            dist[b] = dist[a] + c
            updated = True
    if not updated:
        break

has_neg_cycle = False
for a,b,c in data:
    if dist[a] != INF and dist[b] > dist[a] + c:
        has_neg_cycle = True
        break

if has_neg_cycle:
    print(-1)
else:
    for i in range(2, n+1):
        if dist[i] == INF:
            print(-1)
        else:
            print(dist[i])
print(count)  

문제 핵심 요약:

해결 전략을 세우며 가장 먼저 고민한 것은 “어떤 회의를 먼저 선택해야 이후 선택의 폭이 넓어질까”였다.

이 질문에 대한 답은 회의의 시작 시간이 아니라 끝나는 시간에 있었다. 빨리 끝나는 회의를 먼저 선택할수록 다음 회의를 배치할 수 있는 시간이 많아지고, 그 결과 더 많은 회의를 선택할 수 있다고 판단했다.

이 순간, 이 문제가 그리디 알고리즘이라는 확신이 들었다.


문제 접근

1번 도시에서 출발해 모든 도시까지의 최단 시간을 구하는 문제이다. 간선에 음수 가중치가 존재할 수 있고, 1번 도시에서 도달 가능한 음수 사이클이 있으면 -1을 출력해야 한다. 이 조건 때문에 “단일 시작점 + 음수 간선 + 음수 사이클 판별”이 가능한 벨만-포드 알고리즘을 사용하면 된다.


updated 변수를 둔 이유 (최적화)

한 번의 라운드에서 어떤 거리도 갱신되지 않았다면, 그 이후에도 더 이상 갱신될 일이 없다. 따라서 조기 종료를 통해서 불필요한 반복을 줄이고, 시간 초과를 방지한다. 하지만 이 최적화는 음수 사이클 판별을 대체하진 않는다는 점을 유의하자.


음수 사이클을 따로 검사하는 이유

n-1번의 완화가 끝났다는 것은:

  • 사이클을 쓰지 않는 모든 최단 경로가 반영되었다는 뜻!

하지만 아직 더 줄어드는 간선이 있다면

  • 어떤 사이클을 한 번 더 돌면
  • 거리 값이 계속 감소한다는 의미이다. 즉, 음수 사이클이 존재한다는 것이다.

구현 과정에서 겪은 어려움

① 완화는 한 번으로 끝나지 않는다

  • 완화 1번 = 간선 1개짜리 경로 전달
  • 길이가 긴 경로는 여러 번의 완화가 필요하다.

② updated == False ≠ 음수 사이클 없음

  • updated는 “이번 라운드에서 변화가 있었는지”만 본다.
  • 음수 사이클 존재 여부는 반드시 별도로 검사해야 한다.

③ 음수 사이클 검사는 “계산”이 아니라 “판정”

  • dist를 갱신하지 않는다.
  • “아직 더 줄어들 수 있나?”만 확인한다.