[백준/파이썬] 1005번 ACM Craft 풀이

업데이트:



문제 정보


풀이

문제

건물마다 건설 시간이 있고, 선행 건물 규칙(X를 지은 뒤 Y 가능)이 주어질 때 목표 건물 W를 가장 빨리 완성하는 시간을 구하는 문제입니다.

핵심은 단순히 선행 건물 개수를 세는 게 아니라,
W까지 오는 여러 경로 중 가장 오래 걸리는 경로 시간을 정확히 계산해야 한다는 점입니다.

  • 자세한 문제 및 입출력 예제는 상단의 문제 출처(백준 홈페이지)를 참조해주세요

코드

import sys
from collections import deque

read = sys.stdin.readline

t = int(read())
answers = []

for _ in range(t):
    n, k = map(int, read().split())
    build_time = [0] + list(map(int, read().split()))

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

    for _ in range(k):
        x, y = map(int, read().split())
        graph[x].append(y)
        indegree[y] += 1

    target = int(read())

    # dp[i]: i번 건물을 "완성"할 수 있는 가장 빠른 시간
    dp = [0] * (n + 1)
    q = deque()

    # 선행 건물이 없는 건물부터 시작
    for i in range(1, n + 1):
        if indegree[i] == 0:
            dp[i] = build_time[i]
            q.append(i)

    # 위상 정렬 + 최장 경로 DP
    while q:
        cur = q.popleft()

        for nxt in graph[cur]:
            if dp[nxt] < dp[cur] + build_time[nxt]:
                dp[nxt] = dp[cur] + build_time[nxt]

            indegree[nxt] -= 1
            if indegree[nxt] == 0:
                q.append(nxt)

    answers.append(str(dp[target]))

print("\n".join(answers))

설명

이 문제는 DAG(사이클 없는 방향 그래프) 위상 정렬 + DP 조합으로 풉니다.

  • 선행 규칙 X -> Y는 간선으로 보면 방향 그래프입니다.
  • Y를 짓기 전에 X가 끝나야 하므로 indegree(진입차수) 기반 위상 정렬이 가능합니다.
  • dp[Y] = max(dp[Y], dp[X] + build_time[Y]) 로 갱신하면, Y에 도달하는 모든 경로 중 최댓값(가장 오래 걸리는 선행 체인)을 유지할 수 있습니다.

시간 복잡도는 테스트케이스당 O(N + K) 입니다.

즉, 이 문제의 포인트는 “선행 건물 수”가 아니라 “선행 경로 중 최대 누적 시간”을 구하는 것입니다.



댓글남기기