문제 설명
문제
올해 Z대학 컴퓨터공학부에 새로 입학한 민욱이는 학부에 개설된 모든 전공과목을 듣고 졸업하려는 원대한 목표를 세웠다. 어떤 과목들은 선수과목이 있어 해당되는 모든 과목을 먼저 이수해야만 해당 과목을 이수할 수 있게 되어 있다. 공학인증을 포기할 수 없는 불쌍한 민욱이는 선수과목 조건을 반드시 지켜야만 한다. 민욱이는 선수과목 조건을 지킬 경우 각각의 전공과목을 언제 이수할 수 있는지 궁금해졌다. 계산을 편리하게 하기 위해 아래와 같이 조건을 간소화하여 계산하기로 하였다.
한 학기에 들을 수 있는 과목 수에는 제한이 없다.
모든 과목은 매 학기 항상 개설된다.
모든 과목에 대해 각 과목을 이수하려면 최소 몇 학기가 걸리는지 계산하는 프로그램을 작성하여라.
입력
첫 번째 줄에 과목의 수 N(1≤N≤1000)과 선수 조건의 수 M(0≤M≤500000)이 주어진다. 선수과목 조건은 M개의 줄에 걸쳐 한 줄에 정수 A B 형태로 주어진다. A번 과목이 B번 과목의 선수과목이다. A<B인 입력만 주어진다. (1≤A<B≤N)
출력
1번 과목부터 N번 과목까지 차례대로 최소 몇 학기에 이수할 수 있는지를 한 줄에 공백으로 구분하여 출력한다.
풀이 과정
- 위상 정렬 알고리즘 사용
- 진입 차수가 0인 노드들을 방문한다.
- 진입 차수가 0인 노드에 연결된 간선을 제거해준다.
- 간선 제거로 인해 진입차수가 0이 되는 노드들을 다음에 방문한다.
- 위 알고리즘 과정이 선수과목과 같음.
- 자바1 -> 자바2를 들어야 한다고 가정
- 자바1의 진입 차수는 0이고, 자바2의 진입 차수는 1이므로 자바1 먼저 방문하고, 자바2를 방문하여야 함.
- 큐에 노드 뿐만 아니라 학기도 같이 저장하여 준 다음, 방문 시 각 과목의 학기를 따로 저장
풀이 과정
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:])
'알고리즘[Python] > 백준 알고리즘' 카테고리의 다른 글
[ 16562 ] [ BFS ] 친구비 (0) | 2021.08.17 |
---|---|
[ 10448 ] [ 완전 탐색 ] 유레카 이론 (0) | 2021.08.17 |
[ 5639 ] [ Tree ] 이진 검색 트리 (0) | 2021.08.14 |
[ 4963 ] [BFS] 섬의 개수 (0) | 2021.08.12 |
[ 9935 ] [ Stack ] 문자열 폭발 (0) | 2021.08.12 |