각 온라인 강의는 선수 강의가 있을 수 있는데, 선수 강의가 있는 강의는 선수 강의를 먼저 들어야만 해당 강의를 들을 수 있다.
총 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
개의 줄에는 각 강의의 강의 시간과 그 강의를 듣기 위해 먼저 들어야 하는 강의들의 번호가 자연수로 주어지며, 각 자연수는 공백으로 구분한다.
각 강의 번호는 1부터 N
까지로 구성되며, 각 줄은 -1
로 끝난다.
출력조건
N
개의 강의에 대하여 수강하기까지 걸리는 최소 시간을 한 줄에 하나씩 출력한다.
from collections import deque
import copy
v = int(input())
#모든 진입차수 0으로 초기화
indegree = [0] * (v + 1)
graph = [[] for i in range(v + 1)]
#각 강의 시간 0으로 초기화
time = [0] * (v + 1)
for i in range(1, v + 1):
data = list(map(int, input().split()))
time[i] = data[0] #첫 번째 수는 시간 정보
for x in data[1:-1]:
indegree[i] += 1 #진입차수 증가
graph[x].append(i)
def topology_sort():
#수행 결과를 담을 리스트
result = copy.deepcopy(time)
q = deque()
#처음 시작은 진입차수가 0인 노드를 큐에 삽입
for i in range(1, v + 1):
if indegree[i] == 0:
q.append(i)
#큐가 빌 때까지 반복
while q:
#큐에서 원소 꺼내기
now = q.popleft()
for i in graph[now]:
result[i] = max(result[i], result[now] + time[i]) #현재보다 강의 시간이 오래걸리는 경우 시간 값을 저장
indegree[i] -= 1 #진입차수 감소
#새롭게 진입차수가 0이 되는 노드를 큐에 삽입
if indegree[i] == 0:
q.append(i)
for i in range(1, v + 1):
print(result[i])
topology_sort()
각 노드에 대하여 인접한 노드를 확인할 때, 인접한 노드에 대하여 현재보다 강의 시간이 더 긴 경우를 찾는다면, 더 오랜 시간이 걸리는 경우의 시간 값을 저장하는 방식으로 결과 테이블을 갱신하여 답을 구할 수 있다.
최종적으로 각 강의를 수강하기까지의 최소 시간을 result
리스트 변수에 담도록 하였다.
처음에 각 강의 시간은 time
리스트 변수에 담겨 있는데, 위상 정렬 함수의 초기 부분에서 deepcopy()
함수를 이용하여 time
리스트 변수의 값을 복사하여 result
리스트 변수의 값으로 설정하는 작업이 수행된다.
deepcopy()
함수를 사용한다.
#include <bits/stdc++.h>
using namespace std;
// 노드의 개수(V)
int v;
// 모든 노드에 대한 진입차수는 0으로 초기화
int indegree[501];
// 각 노드에 연결된 간선 정보를 담기 위한 연결 리스트 초기화
vector<int> graph[501];
// 각 강의 시간을 0으로 초기화
int times[501];
// 위상 정렬 함수
void topologySort() {
vector<int> result(501); // 알고리즘 수행 결과를 담을 리스트
for (int i = 1; i <= v; i++) {
result[i] = times[i];
}
queue<int> q; // 큐 라이브러리 사용
// 처음 시작할 때는 진입차수가 0인 노드를 큐에 삽입
for (int i = 1; i <= v; i++) {
if (indegree[i] == 0) {
q.push(i);
}
}
// 큐가 빌 때까지 반복
while (!q.empty()) {
// 큐에서 원소 꺼내기
int now = q.front();
q.pop();
// 해당 원소와 연결된 노드들의 진입차수에서 1 빼기
for (int i = 0; i < graph[now].size(); i++) {
result[graph[now][i]] = max(result[graph[now][i]], result[now] + times[graph[now][i]]);
indegree[graph[now][i]] -= 1;
// 새롭게 진입차수가 0이 되는 노드를 큐에 삽입
if (indegree[graph[now][i]] == 0) {
q.push(graph[now][i]);
}
}
}
// 위상 정렬을 수행한 결과 출력
for (int i = 1; i <= v; i++) {
cout << result[i] << '\n';
}
}
int main(void) {
cin >> v;
// 방향 그래프의 모든 간선 정보를 입력받기
for (int i = 1; i <= v; i++) {
// 첫 번째 수는 시간 정보를 담고 있음
int x;
cin >> x;
times[i] = x;
// 해당 강의를 듣기 위해 먼저 들어야 하는 강의들의 번호 입력
while (true) {
cin >> x;
if (x == -1) break;
indegree[i] += 1;
graph[x].push_back(i);
}
}
topologySort();
}
import java.util.*;
public class Main {
// 노드의 개수(V)
public static int v;
// 모든 노드에 대한 진입차수는 0으로 초기화
public static int[] indegree = new int[501];
// 각 노드에 연결된 간선 정보를 담기 위한 연결 리스트 초기화
public static ArrayList<ArrayList<Integer>> graph = new ArrayList<ArrayList<Integer>>();
// 각 강의 시간을 0으로 초기화
public static int[] times = new int[501];
// 위상 정렬 함수
public static void topologySort() {
int[] result = new int[501]; // 알고리즘 수행 결과를 담을 배열
for (int i = 1; i <= v; i++) {
result[i] = times[i];
}
Queue<Integer> q = new LinkedList<>(); // 큐 라이브러리 사용
// 처음 시작할 때는 진입차수가 0인 노드를 큐에 삽입
for (int i = 1; i <= v; i++) {
if (indegree[i] == 0) {
q.offer(i);
}
}
// 큐가 빌 때까지 반복
while (!q.isEmpty()) {
// 큐에서 원소 꺼내기
int now = q.poll();
// 해당 원소와 연결된 노드들의 진입차수에서 1 빼기
for (int i = 0; i < graph.get(now).size(); i++) {
result[graph.get(now).get(i)] = Math.max(result[graph.get(now).get(i)], result[now] + times[graph.get(now).get(i)]);
indegree[graph.get(now).get(i)] -= 1;
// 새롭게 진입차수가 0이 되는 노드를 큐에 삽입
if (indegree[graph.get(now).get(i)] == 0) {
q.offer(graph.get(now).get(i));
}
}
}
// 위상 정렬을 수행한 결과 출력
for (int i = 1; i <= v; i++) {
System.out.println(result[i]);
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
v = sc.nextInt();
// 그래프 초기화
for (int i = 0; i <= v; i++) {
graph.add(new ArrayList<Integer>());
}
// 방향 그래프의 모든 간선 정보를 입력받기
for (int i = 1; i <= v; i++) {
// 첫 번째 수는 시간 정보를 담고 있음
int x = sc.nextInt();
times[i] = x;
// 해당 강의를 듣기 위해 먼저 들어야 하는 강의들의 번호 입력
while (true) {
x = sc.nextInt();
if (x == -1) break;
indegree[i] += 1;
graph.get(x).add(i);
}
}
topologySort();
}
}