문제
https://www.acmicpc.net/problem/1005
1005번: ACM Craft
첫째 줄에는 테스트케이스의 개수 T가 주어진다. 각 테스트 케이스는 다음과 같이 주어진다. 첫째 줄에 건물의 개수 N과 건물간의 건설순서 규칙의 총 개수 K이 주어진다. (건물의 번호는 1번부
www.acmicpc.net
문제 접근 방식
두 노드간 관계가 주어지기 때문에 위상정렬을 사용하려 했다. 또한, 특정 노드를 가장 빨리 짓기 위해서는 이전에 선행되었던 노드들의 건설이 동시에 이뤄져야한다.(예시에서 2,3번이 동시에 건설되어야함. 2 > 3 이런식으로 순차적으로 건설 X). 선행 노드(2,3번)의 건설이 모두 완료되어야 다음 노드(4번)를 진행할 수 있기 때문에 선행 노드까지의 건설 시간을 비교해야 했고, 이 건설 시간을 저장할 자료구조가 필요했다.
아래와 같이 특정 노드까지 걸리는 시간을 저장하는 자료구조를 만들었고, 이를 활용해서 점화식을 세울 수 있었다(DP)
1. 점화식 정의
total_costs[i] = i 노드까지 걸리는 최소 시간
2. 점화식
total_costs[i] = max(total_costs[j]+cost[i]) //j = i의 선행 노드들, costs[i] = i 노드 건설 시간
위상정렬을 통해 노드들을 순회하고, 이웃한 노드들의 진입차수를 -1 할 때 total_costs[i]( i 까지의 최소 시간) 도 같이 갱신해준다. 이렇게 하면 위상정렬을 완료할 때, 각 노드까지의 최소시간이 total_costs 에 저장된다.
시간 복잡도
위상정렬을 하기 때문에 O(V+E) 가 걸리며, 점화식을 갱신하는데 걸리는 시간은 따로 발생하지 않는다. 그러므로 전체 시간복잡도는 O(V+E)이고, V=1e3 , E=1e5 이기 때문에 시간내에 동작한다.
코드
import sys
input=sys.stdin.readline
print=sys.stdout.write
if __name__=='__main__':
t=int(input())
for _ in range(t):
##### 입력처리 #####
n, k = map(int, input().split())
adj = [[] for _ in range(n + 1)]
costs = list(map(int, input().split()))
costs.insert(0, 0)
## total_costs[i] = i 노드까지 오는데 걸리는 최소비용
total_costs = [0] * (n + 1)
in_degree = [0] * (n + 1)
# 그래프 및 진입차수 초기화
for _ in range(k):
a, b = map(int, input().split())
adj[a].append(b)
in_degree[b] += 1
end_point = int(input())
##### 입력처리 완료 #####
##### 큐에 진입차수가 0 인 노드를 넣어주고, 해당 노드의 total_costs[i] 를 자신의 cost로 갱신한다.
q = []
for i in range(1, n + 1):
if in_degree[i] == 0:
q.append(i)
total_costs[i] = costs[i]
while q:
now = q.pop(0)
for next in adj[now]:
# [now 까지의 최소비용] + [next 비용] 을 구하고, 이전에 구한 값과 비교하여 큰 값으로 갱신한다
total_costs[next] = max(total_costs[next], total_costs[now] + costs[next])
in_degree[next] -= 1
if in_degree[next] == 0:
q.append(next)
print(str(total_costs[end_point])+'\n')
회고
위상 정렬을 사용하여 그래프를 탐색할 때 어떻게 DP를 활용할 수 있는지 경험할 수 있었다.
'문제풀이 > 백준' 카테고리의 다른 글
백준 3665 최종순위 문제풀이 (2) | 2024.01.29 |
---|---|
백준 1766 문제집 문제풀이 (1) | 2024.01.29 |
백준 2252 줄 세우기 문제풀이 (0) | 2024.01.27 |
백준 2887 행성터널 문제풀이 (1) | 2024.01.25 |
백준 1647 도시 분할 계획 문제풀이 (1) | 2024.01.24 |