ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준] 14567번 선수과목
    Algorithm Study/Python 2021. 8. 10. 02:11

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

     

    14567번: 선수과목 (Prerequisite)

    3개의 과목이 있고, 2번 과목을 이수하기 위해서는 1번 과목을 이수해야 하고, 3번 과목을 이수하기 위해서는 2번 과목을 이수해야 한다.

    www.acmicpc.net

    문제

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

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

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

     

    입력

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

     

    출력

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

     

     

    풀이

    위상정렬에 관한 문제이다. 위상 정렬은 다음에 따로 개념적으로 정리해야할거 같다.

    위상 정렬의 경우 indegree(나에게로 들어오는 edge의 수)가 0이 될 때마다 나를 수행하면 되는 것이 기본이다.
    입력으로 받는 값들로 indegree를 설정해주고 처음 0인 Node부터 시작해서 탐색을 진행하고 
    0이 될때마다 해당 Node를 수행했다고 가정하면 언제 해당 과목을 이수할 수 있는지 구할 수 있다.

     

    for i in range(K):
        pre, next = map(int, sys.stdin.readline().split())
        indegree[next] += 1
        graph[pre].append(next)

    입력 받는 값을 이용하여 indegree의 갯수를 indegree 리스트에 저장했다.

     

    dq = deque()
    for i in range(1, N+1):
        if indegree[i] == 0:
            dq.append(i)
            answer[i] = 1

    제일 처음 시작점을 잡기 위해서 indegree가 0인 지점들을 dq에 추가해줬다.

     

    while dq:
        now = dq.popleft()
        for i in graph[now]:
            indegree[i] -= 1
            answer[i] = answer[now] + 1
            if indegree[i] == 0:
                dq.append(i)
    
    print(*answer[1:])

    dq를 탐색하면서 탐색한 지점의 indegree를 1씩 감소시킨다 감소 시켰을 때 0이 되면 dq에 넣는 방식으로 구현하였다.

     

     

    전체 코드

    import sys
    from collections import deque
    from collections import defaultdict
    
    N, K = map(int, sys.stdin.readline().split())
    indegree = [0 for _ in range(N + 1)]
    answer =  [0 for _ in range(N + 1)]
    graph = defaultdict(list)
    
    for i in range(K):
        pre, next = map(int, sys.stdin.readline().split())
        indegree[next] += 1
        graph[pre].append(next)
    
    dq = deque()
    for i in range(1, N+1):
        if indegree[i] == 0:
            dq.append(i)
            answer[i] = 1
    
    while dq:
        now = dq.popleft()
        for i in graph[now]:
            indegree[i] -= 1
            answer[i] = answer[now] + 1
            if indegree[i] == 0:
                dq.append(i)
    
    print(*answer[1:])

     

    위상정렬의 개념을 알고 있으면 쉽게풀 수 있는 문제이지만 다시 개념을 정리할 필요가 있다고 생각한다.

    'Algorithm Study > Python' 카테고리의 다른 글

    [백준] 16938번 캠프 준비  (0) 2021.08.11
    [백준] 14497번 주난의 난  (0) 2021.08.10
    [백준] 1726번 로봇  (0) 2021.07.28
    [백준] 1715번 카드 정렬하기  (0) 2021.07.27
    [백준] 1541번 잃어버린 괄호  (0) 2021.07.27

    댓글

From BlackHair