(Python) 백준 14567

Lee Yechan·2024년 2월 19일
0

알고리즘 문제 풀이

목록 보기
56/60
post-thumbnail

백준 14567

시간 제한메모리 제한제출정답맞힌 사람정답 비율
5 초256 MB56063640278765.469%

문제

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

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

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

입력

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

출력

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


답안

import sys
from collections import deque

def initialize_variables():
    v, e = map(int, sys.stdin.readline().split())
    indegrees = [0] * (v+1)
    edges = [[] for _ in range(v+1)]
    for _ in range(e):
        src, dest = map(int, sys.stdin.readline().split())
        indegrees[dest] += 1
        edges[src].append(dest)
    return v, e, indegrees, edges

def initialize_queue():
    queue = deque([])
    for i in range(1, v+1):
        if indegrees[i] == 0:
            queue.append((1, i))  # (depth, node number)
    return queue

# topological sorting
def solve(v, e, indegrees, edges, queue):
    result = [1] * (v+1)
    while queue:
        depth, node = queue.popleft()
        result[node] = max(result[node], depth)
        for next_node in edges[node]:
            indegrees[next_node] -= 1
            if indegrees[next_node] == 0:
                queue.append((depth+1, next_node))
    return result[1:]

v, e, indegrees, edges = initialize_variables()
queue = initialize_queue()
answer = solve(v, e, indegrees, edges, queue)
print(' '.join(map(str, answer)))

풀이

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

위 문제를 풀다가 시간이 너무 오래 걸려 이 문제의 해결의 실마리를 찾아보았고, 위상 정렬을 이용해 문제를 해결할 수 있겠다는 생각이 들었다.

위상 정렬은 DAG(Directed Acyclic Graph)에서 사용할 수 있는 방법으로, dependency가 있는 스케줄링에 활용할 수 있다.

https://en.wikipedia.org/wiki/Topological_sorting

위상 정렬의 개념을 익혀보기 위해, 위상 정렬 개념을 활용해 쉽게 풀 수 있는 이 문제를 먼저 한 번 풀어보았다.

def solve(v, e, indegrees, edges, queue):
    result = [1] * (v+1)
    while queue:
        depth, node = queue.popleft()
        result[node] = max(result[node], depth)
        for next_node in edges[node]:
            indegrees[next_node] -= 1
            if indegrees[next_node] == 0:
                queue.append((depth+1, next_node))
    return result[1:]

이 풀이에서 가장 중요한 부분은 solve() 함수이다. 그래프(edges)는 adjacency list representation으로 저장되어 있고, queue에는 indegree가 0인 노드들이 들어가 있다.

queue에 element를 넣고 빼기를 반복하며 result에 해당 노드의 depth를 기록한다.

queue에서 빠지는 노드에 연결되어 있던 다른 노드의 indegree를 하나씩 줄이고, 새롭게 indegree가 0이 되는 노드를 큐에 추가하며, 연결된 모든 노드를 살펴본다.

모든 노드의 depth를 return하여, 이를 출력한다.

profile
이예찬

0개의 댓글