14567번: 선수과목 (Prerequisite)
3개의 과목이 있고, 2번 과목을 이수하기 위해서는 1번 과목을 이수해야 하고, 3번 과목을 이수하기 위해서는 2번 과목을 이수해야 한다.
www.acmicpc.net
문제
올해 Z대학 컴퓨터공학부에 새로 입학한 민욱이는 학부에 개설된 모든 전공과목을 듣고 졸업하려는 원대한 목표를 세웠다. 어떤 과목들은 선수과목이 있어 해당되는 모든 과목을 먼저 이수해야만 해당 과목을 이수할 수 있게 되어 있다. 공학인증을 포기할 수 없는 불쌍한 민욱이는 선수과목 조건을 반드시 지켜야만 한다. 민욱이는 선수과목 조건을 지킬 경우 각각의 전공과목을 언제 이수할 수 있는지 궁금해졌다. 계산을 편리하게 하기 위해 아래와 같이 조건을 간소화하여 계산하기로 하였다.
- 한 학기에 들을 수 있는 과목 수에는 제한이 없다.
- 모든 과목은 매 학기 항상 개설된다.
모든 과목에 대해 각 과목을 이수하려면 최소 몇 학기가 걸리는지 계산하는 프로그램을 작성하여라.
입력
첫 번째 줄에 과목의 수 N(1 ≤ N ≤ 1000)과 선수 조건의 수 M(0 ≤ M ≤ 500000)이 주어진다. 선수과목 조건은 M개의 줄에 걸쳐 한 줄에 정수 A B 형태로 주어진다. A번 과목이 B번 과목의 선수과목이다. A < B인 입력만 주어진다. (1 ≤ A < B ≤ N)
출력
1번 과목부터 N번 과목까지 차례대로 최소 몇 학기에 이수할 수 있는지를 한 줄에 공백으로 구분하여 출력한다.
코드
import sys
input = sys.stdin.readline
from collections import deque
n, m = map(int, input().split())
graph = [[] for _ in range(n+1)]
indegree = [0] * (n+1)
for _ in range(m):
a, b = map(int, input().split())
graph[a].append(b)
indegree[b] += 1
ans = [0] * (n+1)
semester = [0] * (n+1)
q = deque()
for i in range(1, n+1):
if indegree[i] == 0: # 진입차수가 0인 노드들 큐에 삽입
q.append((i, 1))
semester[i] = 1 # 1학기에 수강 가능한 과목들
while q:
subject, cnt = q.popleft()
if graph[subject]:
for next_node in graph[subject]:
indegree[next_node] -= 1
if indegree[next_node] == 0: # 진입차수가 0이 되면 큐에 삽입
q.append((next_node, cnt + 1))
semester[next_node] = cnt + 1
print(*semester[1:n+1])
위상정렬(Topological Sort)
사이클이 없는 방향 그래프인 비순환 방향 그래프(DAG)에서 정점을 선형으로 정렬하는 것이다.
쉽게 말하자면 순서가 정해져있는 작업들을 차례대로 수행해야 할 때 순서대로 정렬해주는 알고리즘이다.
알고리즘에 대해 간단히 설명하자면
먼저 진입 차수에 대해 알아야 하는데, 진입 차수란 다른 노드에서 자신으로 들어오는 간선의 개수를 말한다. 예를 들어, 다른 노드들에서 N번 노드 방향으로 향하는 간선이 3개 있다고 하면 N번 노드의 진입 차수는 3이다. 진입 차수가 0인 노드는 다른 노드에서 자기 자신으로 들어오는 노드가 없다는 뜻이므로 선행되는 노드가 없다는 뜻. 즉, 순서가 맨 앞인 것이다.
위상정렬의 과정을 살펴보면
- 큐에 진입차수가 0인 노드들을 넣어준다.
- 큐에 넣어진 노드들에서 연결된 간선을 제거하고 연결되어있던 다음 노드들의 진입 차수를 1씩 줄여주면 된다. 이 때 진입 차수를 감소켰더니 0이 된 노드들은 또 큐에 넣어준다.
- 2의 작업을 계속 반복하면 노드들을 순서대로 정렬해줄 수 있다.
'문제풀이 > 위상정렬' 카테고리의 다른 글
[Python/파이썬] 백준 2252번 줄 세우기 (0) | 2023.03.31 |
---|---|
[Python/파이썬] 백준 1005번 ACM Craft (0) | 2023.03.31 |
[Python/파이썬] 백준 2623번 음악프로그램 (0) | 2022.09.14 |
[Python/파이썬] 백준 2252번 줄 세우기 (0) | 2022.09.08 |
[Python/파이썬] 백준 1005번 ACM Craft (0) | 2022.08.31 |
14567번: 선수과목 (Prerequisite)
3개의 과목이 있고, 2번 과목을 이수하기 위해서는 1번 과목을 이수해야 하고, 3번 과목을 이수하기 위해서는 2번 과목을 이수해야 한다.
www.acmicpc.net
문제
올해 Z대학 컴퓨터공학부에 새로 입학한 민욱이는 학부에 개설된 모든 전공과목을 듣고 졸업하려는 원대한 목표를 세웠다. 어떤 과목들은 선수과목이 있어 해당되는 모든 과목을 먼저 이수해야만 해당 과목을 이수할 수 있게 되어 있다. 공학인증을 포기할 수 없는 불쌍한 민욱이는 선수과목 조건을 반드시 지켜야만 한다. 민욱이는 선수과목 조건을 지킬 경우 각각의 전공과목을 언제 이수할 수 있는지 궁금해졌다. 계산을 편리하게 하기 위해 아래와 같이 조건을 간소화하여 계산하기로 하였다.
- 한 학기에 들을 수 있는 과목 수에는 제한이 없다.
- 모든 과목은 매 학기 항상 개설된다.
모든 과목에 대해 각 과목을 이수하려면 최소 몇 학기가 걸리는지 계산하는 프로그램을 작성하여라.
입력
첫 번째 줄에 과목의 수 N(1 ≤ N ≤ 1000)과 선수 조건의 수 M(0 ≤ M ≤ 500000)이 주어진다. 선수과목 조건은 M개의 줄에 걸쳐 한 줄에 정수 A B 형태로 주어진다. A번 과목이 B번 과목의 선수과목이다. A < B인 입력만 주어진다. (1 ≤ A < B ≤ N)
출력
1번 과목부터 N번 과목까지 차례대로 최소 몇 학기에 이수할 수 있는지를 한 줄에 공백으로 구분하여 출력한다.
코드
import sys input = sys.stdin.readline from collections import deque n, m = map(int, input().split()) graph = [[] for _ in range(n+1)] indegree = [0] * (n+1) for _ in range(m): a, b = map(int, input().split()) graph[a].append(b) indegree[b] += 1 ans = [0] * (n+1) semester = [0] * (n+1) q = deque() for i in range(1, n+1): if indegree[i] == 0: # 진입차수가 0인 노드들 큐에 삽입 q.append((i, 1)) semester[i] = 1 # 1학기에 수강 가능한 과목들 while q: subject, cnt = q.popleft() if graph[subject]: for next_node in graph[subject]: indegree[next_node] -= 1 if indegree[next_node] == 0: # 진입차수가 0이 되면 큐에 삽입 q.append((next_node, cnt + 1)) semester[next_node] = cnt + 1 print(*semester[1:n+1])
위상정렬(Topological Sort)
사이클이 없는 방향 그래프인 비순환 방향 그래프(DAG)에서 정점을 선형으로 정렬하는 것이다.
쉽게 말하자면 순서가 정해져있는 작업들을 차례대로 수행해야 할 때 순서대로 정렬해주는 알고리즘이다.
알고리즘에 대해 간단히 설명하자면
먼저 진입 차수에 대해 알아야 하는데, 진입 차수란 다른 노드에서 자신으로 들어오는 간선의 개수를 말한다. 예를 들어, 다른 노드들에서 N번 노드 방향으로 향하는 간선이 3개 있다고 하면 N번 노드의 진입 차수는 3이다. 진입 차수가 0인 노드는 다른 노드에서 자기 자신으로 들어오는 노드가 없다는 뜻이므로 선행되는 노드가 없다는 뜻. 즉, 순서가 맨 앞인 것이다.
위상정렬의 과정을 살펴보면
- 큐에 진입차수가 0인 노드들을 넣어준다.
- 큐에 넣어진 노드들에서 연결된 간선을 제거하고 연결되어있던 다음 노드들의 진입 차수를 1씩 줄여주면 된다. 이 때 진입 차수를 감소켰더니 0이 된 노드들은 또 큐에 넣어준다.
- 2의 작업을 계속 반복하면 노드들을 순서대로 정렬해줄 수 있다.
'문제풀이 > 위상정렬' 카테고리의 다른 글
[Python/파이썬] 백준 2252번 줄 세우기 (0) | 2023.03.31 |
---|---|
[Python/파이썬] 백준 1005번 ACM Craft (0) | 2023.03.31 |
[Python/파이썬] 백준 2623번 음악프로그램 (0) | 2022.09.14 |
[Python/파이썬] 백준 2252번 줄 세우기 (0) | 2022.09.08 |
[Python/파이썬] 백준 1005번 ACM Craft (0) | 2022.08.31 |