위상정렬이란 순서가 정해져 있는 작업을 수행할 때 그 순서를 결정하기 위한 알고리즘을 말한다.
위상정렬을 적용하기 위한 조건은
DAG(Direted Acyclic Graph) 즉, 사이클이 발생하지 않는 방향그래프에만 적용이 가능하다.
DAG의 예시
![]()
DAG가 아닌 예시
![]()
두번째 그림처럼 순환이 발생할 경우 위상정렬 알고리즘을 적용할 수 없다.
(물론 다시 수시 정시를 보고싶지도 않다🥕)
문제로 돌아가서 해당 문제는 위상정렬로 접근이 가능하다.
문제의 입력예시1을 보면
1번 학생 뒤에 3번학생, 2번학생 뒤에 3번학생이 서야 하므로 그래프는 다음과 같이 나타낼 수 있다.
사이클이 발생하지 않는 방향 그래프이기 때문에 위상 정렬로 구현 가능하다.
입력예시 1을 기준으로 진입차수는 다음과 같다
import sys
from collections import deque
ans = []
n,m = map(int, sys.stdin.readline().split())
queue = deque([])
degree = [0] * (n+1)
adj = [[] for _ in range(n+1)]
#1. 진입차수 확인
for _ in range(m):
a,b = map(int, sys.stdin.readline().rstrip().split())
adj[a].append(b)
degree[b]+=1
#2.진입차수가 0인 정점을 큐에 삽입
for i in range(1, n+1):
if(degree[i] == 0):
queue.append(i)
while queue:
#3 큐의 원소들을 꺼내 연결된 모든 간선 제거
temp = queue.popleft()
ans.append(temp)
for i in adj[temp]:
#4. 간선 제거 이후 진입차수가 0인 정점 큐에 삽입(반복)
degree[i]-=1
if degree[i] == 0 :
queue.append(i)
#출력
print(*ans)
처음에 위상정렬이라는 개념을 모르고 문제를 풀다 보니 개념이 많이 생소했는데 다른 기술 블로그를 보며 개념을 익히는데 도움을 많이 받았습니다.
항상 열심히 배운다는 자세로 겸손하게 공부를 해야겠단 생각이 들었습니다.
참조:
안경잡이 개발자
hongcoding.tistory.com
동빈나 유투브