알고리즘
[백준] 선수과목 - Java
BGK97
2025. 2. 28. 17:54
문제 출처
https://www.acmicpc.net/problem/14567
문제
올해 Z대학 컴퓨터공학부에 새로 입학한 민욱이는 학부에 개설된 모든 전공과목을 듣고 졸업하려는 원대한 목표를 세웠다. 어떤 과목들은 선수과목이 있어 해당되는 모든 과목을 먼저 이수해야만 해당 과목을 이수할 수 있게 되어 있다. 공학인증을 포기할 수 없는 불쌍한 민욱이는 선수과목 조건을 반드시 지켜야만 한다. 민욱이는 선수과목 조건을 지킬 경우 각각의 전공과목을 언제 이수할 수 있는지 궁금해졌다. 계산을 편리하게 하기 위해 아래와 같이 조건을 간소화하여 계산하기로 하였다.
- 한 학기에 들을 수 있는 과목 수에는 제한이 없다.
- 모든 과목은 매 학기 항상 개설된다.
모든 과목에 대해 각 과목을 이수하려면 최소 몇 학기가 걸리는지 계산하는 프로그램을 작성하여라.
입력
첫 번째 줄에 과목의 수 N(1 ≤ N ≤ 1000)과 선수 조건의 수 M(0 ≤ M ≤ 500000)이 주어진다. 선수과목 조건은 M개의 줄에 걸쳐 한 줄에 정수 A B 형태로 주어진다. A번 과목이 B번 과목의 선수과목이다. A < B인 입력만 주어진다. (1 ≤ A < B ≤ N)
출력
1번 과목부터 N번 과목까지 차례대로 최소 몇 학기에 이수할 수 있는지를 한 줄에 공백으로 구분하여 출력한다.
예제 입력 1
3 2
2 3
1 2
예제 출력 1
1 2 3
예제 입력 2
6 4
1 2
1 3
2 5
4 5
예제 출력 2
1 2 2 1 3 1
힌트
3개의 과목이 있고, 2번 과목을 이수하기 위해서는 1번 과목을 이수해야 하고, 3번 과목을 이수하기 위해서는 2번 과목을 이수해야 한다.
풀이 방법
- 인접 리스트를 활용하여 선수과목 -> 이전 과목을 짝으로 연결해준다.
- 이후 1과목을 제외한(1과목은 무조건 1학기에 들을 수 있으므로) 나머지를 탐방하면서, 해당 수업을 들을 수 있는 학기 + 1만큼 값을 증가시켜주고, term 배열에 추가해준다.
풀이 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.StringTokenizer;;
public class Main {
static int N, M;
static List<List<Integer>> adjList;
static int[] term;
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
StringBuilder sb = new StringBuilder();
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
term = new int[N + 1];
//인접 리스트 생성
adjList = new ArrayList<>();
for(int i = 0; i < N + 1; i++) {
adjList.add(new ArrayList<>());
}
//과목 입력후 인접 리스트에 추가
for(int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
int u = Integer.parseInt(st.nextToken());
int v = Integer.parseInt(st.nextToken());
adjList.get(v).add(u);
}
//1과목은 무조건 선수강
term[1] = 1;
int max = 0;
for(int i = 2; i < N + 1; i++) {
if(adjList.get(i).size() == 0) {
term[i] = 1;
}
else {
for(int v: adjList.get(i)) {
if(max <= term[v]) {
max = term[v] + 1;
}
}
term[i] = max;
max = 0;
}
}
for(int i = 1; i < N + 1; i++) {
sb.append(term[i] + " ");
}
System.out.println(sb.toString());
}
}
결과

회고
- BFS로 풀어보는 방법도 있을 것 같다.