문제 설명


문제

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

한 학기에 들을 수 있는 과목 수에는 제한이 없다.
모든 과목은 매 학기 항상 개설된다.
모든 과목에 대해 각 과목을 이수하려면 최소 몇 학기가 걸리는지 계산하는 프로그램을 작성하여라.

입력

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

출력

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


풀이 과정

  1. 위상 정렬 알고리즘 사용
    • 진입 차수가 0인 노드들을 방문한다.
    • 진입 차수가 0인 노드에 연결된 간선을 제거해준다.
    • 간선 제거로 인해 진입차수가 0이 되는 노드들을 다음에 방문한다.
  2. 위 알고리즘 과정이 선수과목과 같음.
    • 자바1 -> 자바2를 들어야 한다고 가정
    • 자바1의 진입 차수는 0이고, 자바2의 진입 차수는 1이므로 자바1 먼저 방문하고, 자바2를 방문하여야 함.
  3. 큐에 노드 뿐만 아니라 학기도 같이 저장하여 준 다음, 방문 시 각 과목의 학기를 따로 저장

풀이 과정

import sys
from collections import deque

input = sys.stdin.readline

N, M = map(int, input().rstrip().split())

graph = [[] for _ in range(N+1)]
indegree = [0] * (N+1)
semester = [0] * (N+1)
queue = deque()


for _ in range(M):
    src, dest = map(int, input().rstrip().split())
    graph[src].append(dest)
    indegree[dest] += 1

# 초기 진입차수가 0인 노드 등록 
for i in range(1, N+1):
    if indegree[i] == 0:
        queue.append([i, 1])

while queue:
    cur, sem = queue.popleft()
    semester[cur] = sem
    for n in graph[cur]:
        indegree[n] -= 1
        # 진입차수가 0이 되면 들을수 있는 과목이므로 넣어준다.
        if indegree[n] == 0:
            queue.append([n, sem+1])

print(*semester[1:])

+ Recent posts