위상 정렬 좋아
올해 Z대학 컴퓨터공학부에 새로 입학한 민욱이는 학부에 개설된 모든 전공과목을 듣고 졸업하려는 원대한 목표를 세웠다. 어떤 과목들은 선수과목이 있어 해당되는 모든 과목을 먼저 이수해야만 해당 과목을 이수할 수 있게 되어 있다. 공학인증을 포기할 수 없는 불쌍한 민욱이는 선수과목 조건을 반드시 지켜야만 한다. 민욱이는 선수과목 조건을 지킬 경우 각각의 전공과목을 언제 이수할 수 있는지 궁금해졌다. 계산을 편리하게 하기 위해 아래와 같이 조건을 간소화하여 계산하기로 하였다.
모든 과목에 대해 각 과목을 이수하려면 최소 몇 학기가 걸리는지 계산하는 프로그램을 작성하여라.
예제 입력
3 2
2 3
1 2
예제 출력
1 2 3
다이나믹 프로그래밍 위상 정렬
📍 위상 정렬을 사용해 순서가 있는 bfs를 실행해 준다. 몇 학기가 걸리는지는 answer[다음 과목] = answer[현재 수강한 과목] + 1 와 같은 점화식을 사용해 저장해 주었다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Queue;
import java.util.StringTokenizer;
import java.util.ArrayList;
import java.util.LinkedList;
public class BOJ14567_선수과목 {
static ArrayList<ArrayList<Integer>> graph;
static int[] depth, answer;
static Queue<Integer> q;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
graph = new ArrayList<>();
depth = new int[n + 1];
answer = new int[n + 1];
q = new LinkedList<>();
for (int i = 0; i < n + 1; i++) {
graph.add(new ArrayList<>());
}
for (int i = 0; i < m; i++) {
st = new StringTokenizer(br.readLine());
int prev = Integer.parseInt(st.nextToken());
int next = Integer.parseInt(st.nextToken());
graph.get(prev).add(next);
depth[next] += 1;
}
for (int i = 1; i < n + 1; i++) {
if (depth[i] == 0) {
q.offer(i);
answer[i] = 1;
}
}
bfs();
StringBuilder sb = new StringBuilder();
for (int i = 1; i < n + 1; i++) {
sb.append(answer[i] + " ");
}
System.out.println(sb.toString());
}
static void bfs() {
while (!q.isEmpty()) {
int now = q.poll();
for (int next : graph.get(now)) {
if (--depth[next] == 0) {
q.offer(next);
answer[next] = answer[now] + 1;
}
}
}
}
}