알고리즘

[백준] 선수과목 - Java

BGK97 2025. 2. 28. 17:54

문제 출처

https://www.acmicpc.net/problem/14567

문제

올해 Z대학 컴퓨터공학부에 새로 입학한 민욱이는 학부에 개설된 모든 전공과목을 듣고 졸업하려는 원대한 목표를 세웠다. 어떤 과목들은 선수과목이 있어 해당되는 모든 과목을 먼저 이수해야만 해당 과목을 이수할 수 있게 되어 있다. 공학인증을 포기할 수 없는 불쌍한 민욱이는 선수과목 조건을 반드시 지켜야만 한다. 민욱이는 선수과목 조건을 지킬 경우 각각의 전공과목을 언제 이수할 수 있는지 궁금해졌다. 계산을 편리하게 하기 위해 아래와 같이 조건을 간소화하여 계산하기로 하였다.

  1. 한 학기에 들을 수 있는 과목 수에는 제한이 없다.
  2. 모든 과목은 매 학기 항상 개설된다.

모든 과목에 대해 각 과목을 이수하려면 최소 몇 학기가 걸리는지 계산하는 프로그램을 작성하여라.

입력

첫 번째 줄에 과목의 수 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로 풀어보는 방법도 있을 것 같다.