가. 위상이란?
일단 먼저 위상정렬에서 “위상”이 가지는 의미를 알아보자. 위상이란 “어떤 사물이 다른 사물과의 관계 속에서 가지는 위치나 상태”를 의미한다. 즉 위상은 물체 사이의 관계를 의미하고 위상정렬에서는 이 관계가 “어떤 물체의 선행”이라는 의미로 표현된다. 예를들어 A와 B가 있고 A는 항상 B 앞에 나와야한다고 가정한다면 이는A는 B앞에 있어야되는 관계에 있다라고 표현할 수 있고 이는 다시 A는 B앞에 있어야하는 위상에 있다.라고 말할 수 있다는 것이다. 이러한 의미에서 “위상 정렬”은 두 물체 사이의 상관관계가 존재하는 정렬 문제에 풀 수 있다고 추측할 수 있다.
나. 위상 정렬
그렇다면 위상 정렬이란 무엇일까? 바로 아래 그림과 같은 상황이다.

여기서 올바른 순서는 무엇일까?
일 것이다. 그렇다 위에서 말했듯이 자료구조와 알고리즘 사이의 상관관계가 존재하는 것이고. 알고리즘과 고급 알고리즘에서도 상관관계가 존재한다. 이것을 그렇다면 어떻게 풀 것인가를 생각해보자.
다. 진입차수와 진출차수

우리는 위의사진에서 진입차수를 사용할 것이다. 진입차수가 낮은 노드부터 방문할 것이다. 하지만 진입차수가 동일한 경우도 있을 것이다. 이를 해결하기 위해 큐를 사용하여 다음과 같은 알고리즘을 사용할 것이다.
라. 큐를 사용한 알고리즘
1. 진입차수가 0인 모든 노드를 큐에 넣는다.
2. 큐가 빌 때까지 다음 과정을 반복한다.
2.1 큐에서 원소를 꺼내 해당 노드에서 나가는 간선을 그래프에서 제거한다.
2.2 새롭게 진입차수가 0이 된 노드를 큐에 넣는다.
위를 보면 처음에 진입차수가 0인 노드를 큐에 넣고 큐가 빌때까지 빼고 진입차수0 인 노드를 넣고 반복한다.
빼지넣
[[], [3,4] … ] 이런 형식이다.[0,3,...]이다.빼지넣빼지넣 부분의 넣 부분을 지(지우기)에서 지운 노드들에서 체크하여 바로 넣어주는 것을 잊지말자! (넣와 지는 하나!)import sys
from collections import deque
N,M=map(int,sys.stdin.readline().split())
graph=[[] for _ in range(N+1)]
entryCnt=[0]*(N+1)
for _ in range(M):
a,b = map(int,sys.stdin.readline().split())
graph[a].append(b)
entryCnt[b]+=1
result=[]
que=deque()
# 초기넣
for i in range(1,N+1):
if entryCnt[i] == 0:
que.append(i)
# 빼지넣
while que:
# 빼고
node = que.popleft()
result.append(node)
#지우고
for i in graph[node]:
entryCnt[i]-=1
#넣고 -> graph 리스트를 통해 해당 노드와 연결된 노드들만 진입차수 0인지 확인 가능!
if entryCnt[i]==0:
que.append(i)
print(*result)
위상정렬을 할 때, “빼지넣”만 기억하면 된다는 점과 지넣은 하나라는 것을 까먹으면 안된다는 것을 느꼈다. 빼지은는 빼고 지우고 넣고이고 지넣이 하나라는 것은 큐에서 뺀 노드와 연결된 노드의 진입차수를 -1 할 때(간선을 지울때), 그 진입차수를 -1한 노드를 0인지 체크하여 큐에 넣는다는 것이다. 이렇게 하므로서 바로바로 간선지우고 지운 간선과 연결된 노드들만 진입차수가 0인지 체크하므로 순차탐색으로 모든 노드의 진입차수가 0인지 확인할 필요가 없어진다!