백준 - 선수과목 (Prerequisite)[14567]

노력하는 배짱이·2021년 2월 25일
0

백준 알고리즘

목록 보기
16/35
post-thumbnail
post-custom-banner

문제

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

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

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

입력

첫 번째 줄에 과목의 수 N(1≤N≤1000)과 선수 조건의 수 M(0≤M≤500000)이 주어진다. 선수과목 조건은 M개의 줄에 걸쳐 한 줄에 정수 A B 형태로 주어진다. A번 과목이 B번 과목의 선수과목이다. A<B인 입력만 주어진다. (1≤A<B≤N)

출력

1번 과목부터 N번 과목까지 차례대로 최소 몇 학기에 이수할 수 있는지를 한 줄에 공백으로 구분하여 출력한다.

풀이

위상정렬(TopologySort)를 사용하여 풀면 된다.

문제에서 최종적으로 모든 과목에 대해 각 과목을 이수하려면 최소 몇 학기가 걸리는지 구하는 것이기 때문에 별도의 클래스 Subject를 선언하여 semester라는 변수를 통해 학기를 저장했다.

또한 각 과목의 최소 학기를 저장하기 위해 result 이름의 배열을 사용하였다.

topologySort() 메서드안에서 큐에 Subject 객체를 넣는 방식으로 구현을 하였고, 진입차수가 0인 것들을 먼저 큐에 넣어주었다. 이때, 해당 객체의 semester 는 0으로 초기화 한다.

큐가 비어질때까지 하나씩 꺼내어 진입차수를 1씩 감소시키고 진입차수가 0일때 해당 인덱스에 해당하는 부분의 값을 큐에서 꺼낸 객체(now에 해당) semester +1를 해준다.

큐에 다시 넣을 때 semester+1를 한 값을 넣어줘야 한다.

소스

import java.util.*;

class Subject {
	private int index;
	private int semester;

	public Subject(int index, int semester) {
		this.index = index;
		this.semester = semester;
	}

	public int getIndex() {
		return this.index;
	}

	public int getSemester() {
		return this.semester;
	}
}

public class Main {
	public static int n, m;
	public static int[] indegree = new int[500001];

	public static ArrayList<ArrayList<Integer>> graph = new ArrayList<ArrayList<Integer>>();
	public static int result = 0;

	public static void topologySort() {
		// 결과 테이블
		int[] result = new int[n + 1];
		Queue<Subject> q = new LinkedList<>();

		for (int i = 1; i <= n; i++) {
			if (indegree[i] == 0) {
				q.offer(new Subject(i, 0));
			}
		}

		while (!q.isEmpty()) {
			Subject now = q.poll();

			for (int i = 0; i < graph.get(now.getIndex()).size(); i++) {
				indegree[graph.get(now.getIndex()).get(i)] -= 1;
				if (indegree[graph.get(now.getIndex()).get(i)] == 0) {
					result[graph.get(now.getIndex()).get(i)] = now.getSemester() + 1;
					q.offer(new Subject(graph.get(now.getIndex()).get(i), now.getSemester() + 1));
				}
			}
		}

		for (int i = 1; i < result.length; i++) {
			System.out.print((result[i] + 1) + " ");
		}
	}

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);

		n = sc.nextInt();
		m = sc.nextInt();

		for (int i = 0; i <= n; i++) {
			graph.add(new ArrayList<Integer>());
		}

		for (int i = 0; i < m; i++) {
			int a = sc.nextInt();
			int b = sc.nextInt();
			graph.get(a).add(b);
			indegree[b] += 1;
		}

		topologySort();
	}

}
post-custom-banner

0개의 댓글