◎ 문제
철수는 온라인으로 컴퓨터공학강의를 듣고 있다. 이때 각 온라인강의는 선수강의가 있을 수 있는데, 선수 강의가 있는 강의는 선수 강의를 먼저 들어야만 해당강의를 들을 수 있다. 예를들어 '알고리즘’ 강의의 선수 강의로 '자료구조'가 존재한다면, ‘자료구조를 들은 이후에 ‘알고리즘' 강의를 들을 수 있다. 철수는 총 N개의 강의를 듣고자 한다. 모든 강의는 1번부터 N번까지의 번호를 가진다. 또한 동시에 여러 개의 강의를 들을 수 있다고 가정한다. 예를 들어 N=3일 때, 3번강의의 선수 강의로 1번과 2번강의가 있고, 1번과 2번강의는 선수강의가 없다고 가정하자. 그리고 각 강의에 대하여 강의 시간이 다음과 같다고 가정하자.
- 1번 강의: 30시간
- 2번 강의: 20시간
- 3번 강의: 40시간
이 경우 1번 강의를 수강하기까지의 최소 시간은 30시간, 2번 강의를 수강하기까지의 최소 시간은 20시간,3번 강의를 수강하기까지의 최소 시간은 70시간이다.철수가 듣고자 하는 N개의 강의 정보가 주어졌을 때,N개의 강의에 대하여 수강하기까지 걸리는 최소 시간을 각각 출력하는 프로그램을 작성하시오.
입력 조건
- 첫째줄에 철수가 듣고자 하는 강의의 수 N(1≤N≤500)이 주어진다.
- 다음 N개의 줄에는 각 강의의 강의 시간과 그 강의를 듣기 위해 먼저 들어야하는 강의들의 번호가 자연수로 주어지며, 각 자연수는 공백으로 구분한다.
- 이때 강의시간은 100,000이하의 자연수이다.
- 각 강의번호는 1부터 N까지로 구성되며 각줄은 -1로 끝난다.
- 출력 조건
- N개의 강의에 대하여 수강하기까지 걸리는 최소 시간을 한 줄에 하나씩 출력한다
- 입력 예시
5
10 -1
10 1 -1
4 1 -1
4 3 1 -1
3 3 -1
- 출력 예시
10
20
14
18
17
◎ 문제풀이
작업의 순서를 정하는 문제이다. 순서는 '정렬'을 의미한다. 작업에는 선수작업이 있고 이는 방향그래프로 표현된다. 그러므로 위상정렬알고리즘이 연상된다. ( Topology Sort Algorithm )
위상정렬 알고리즘은 위 포스팅을 참고하면 된다.
나는 '최소시간' 출력의 의미를 이해하지 못했다. 이는 위상정렬 알고리즘을 이해하지 못함에서 비롯되었다.
종합설계 과목은 객체지향,JAVA,알고리즘 세가지 선수과목을 가진다. 여기서 객체지향, JAVA, 알고리즘은 순서대로 처리되지 않는다.
객체지향 ➟ JAVA ➟ 알고리즘 ( X )
각 선수과목은 각자의 처리시간을 갖고 동시에 일어난다. 즉, 서로에게 독립적이다. 그러므로 종합설계가 처리되는 시간은 3가지 경우이다.
1) 객체지향 ➟ 종합설계 : 30시간 + 40시간
2) JAVA ➟ 종합설계 : 20시간 + 40시간
3) 알고리즘 ➟ 종합설계 : 60시간 + 40시간
객체지향도 선수과목이 있다. 선수과목을 듣고 객체지향도 들었을 때, 걸리는 시간이 30시간이다. JAVA는 선수과목이 없다. 알고리즘도 선수과목이 있고 선수과목을 듣고 알고리즘을 들었을 때, 걸리는 시간이 60시간이다. 정리하면, JAVA과목을 아무리 20시간만에 들어도, 객체지향 아무리 30시간만에 들어도, 알고리즘 60시간을 들어야 종합설계를 들을수 있다는 의미이다.
( 20 + 30 + 60 )이 아니라, 20,30은 의미없고 60만 의미 있다는 말이다.
그러므로 3가지 경우 중 가장 오래 걸리는 경우가 최적의 경우이다.
1) 객체지향 ➟ 종합설계 : 30시간 + 40시간 : 70시간
2) JAVA ➟ 종합설계 : 20시간 + 40시간 : 60시간
3) 알고리즘 ➟ 종합설계 : 60시간 + 40시간 : 100시간
종합설계 강의 수강완료까지 걸리는 최소시간은 100시간이다. 최대로 최소를 구해야 하는 어려움이 있는 문제이다.
◎ 코드
from collections import deque
import copy
import sys
input = sys.stdin.readline
n = int(input())
indegrees = [0]*(n+1)
time = [0]*(n+1)
graph = [[] for _ in range(n+1)]
for i in range(1,n+1) :
info = list(map(int,input().split()))
time[i] = info[0]
for j in range(1,len(info)) :
sunsu = info[j]
if sunsu != -1 :
graph[sunsu].append(i)
indegrees[i] += 1
else : break
q = deque()
for i in range(1,n+1) :
if indegrees[i] == 0 : q.append(i)
result = copy.deepcopy(time) #값복사
while q :
now = q.popleft()
for next in graph[now] :
result[next] = max(result[next],result[now] + time[next]) #다른 선수과목과 비교하여 큰값을 테이블에 저장하기
indegrees[next] -= 1
if indegrees[next] == 0 : q.append(next)
for i in range(1,n+1) :
print(result[i])
참고자료
'문제풀이 > Graph' 카테고리의 다른 글
[PS] BOJ1756 문제집 ( 위상정렬 ) with JAVA (0) | 2023.08.24 |
---|---|
[PS] BOJ1707 이분그래프 ( graph ) with Python (0) | 2023.07.11 |
[CodingTest] 도시분할계획 ( graph ) (0) | 2023.06.01 |
[CodingTest] 팀 결성 ( Graph 알고리즘 ) (0) | 2023.05.25 |