개념
선후 관계를 지키는 순서
위상 정렬은 방향 간선 마다 가 보다 앞에 오도록 정점을 나열하는 방법입니다. 먼저 끝내야 하는 작업이나 먼저 수강해야 하는 과목이 정해져 있을 때 사용합니다. DAG에서 위상 정렬이 가능하며, 조건을 만족하는 순서는 여러 개일 수 있습니다.
진입 차수를 이용한 처리
진입 차수는 그 정점으로 들어오는 간선의 수입니다. 작업 관계에서는 아직 처리해야 할 선행 작업의 개수에 해당합니다. 진입 차수가 인 정점을 큐에 넣고, 하나씩 꺼내며 나가는 간선을 제거합니다. 간선이 제거되어 진입 차수가 이 된 이웃을 큐에 추가합니다.
아래 그래프에는 정점이 개 있습니다. 진한 정점은 큐에 들어 있는 처리 후보입니다. 아래 표는 남은 진입 차수이고, 점선은 처리하면서 제거한 간선입니다. 처음에는 들어오는 간선이 없는 를 큐에 넣습니다.
을 처리하면 , 를 제거합니다. 의 진입 차수는 이 되어 큐에 들어가지만, 에는 가 남아 있으므로 진입 차수가 입니다. 큐는 앞에서부터 입니다.
를 처리하면 , 도 제거합니다. 의 진입 차수가 모두 이 되어 큐는 가 됩니다. 이후 같은 과정을 반복하면 순서로 모든 정점을 처리할 수 있습니다.
후보를 일반 큐에 넣으면 추가된 순서로 처리합니다. 후보 중 번호가 가장 작은 정점을 먼저 선택하려면 최소 우선순위 큐를 사용합니다.
처리한 정점 수로 방향 사이클 판별하기
진입 차수로 위상 정렬을 수행하면 방향 그래프의 사이클 유무도 판별할 수 있습니다. 큐가 빌 때까지 처리한 정점 수를 , 전체 정점 수를 라고 하면 다음과 같습니다.
| 처리 결과 | 판정 |
|---|---|
| 모든 정점을 처리했으므로 방향 사이클이 없습니다. | |
| 처리할 수 없는 정점이 남았으므로 방향 사이클이 있습니다. |
사이클 안의 각 정점에는 사이클의 이전 정점에서 들어오는 간선이 있습니다. 그 이전 정점을 먼저 처리해야 간선을 제거할 수 있지만, 모든 정점이 같은 조건으로 서로를 기다리므로 진입 차수가 이 되지 않습니다.
앞의 그래프에 를 추가하겠습니다. 진한 간선 가 방향 사이클을 이룹니다. 그래도 의 진입 차수는 이므로 일부 정점은 처리할 수 있습니다.
를 처리한 뒤에는 큐가 비게 됩니다. 는 을, 은 를 기다립니다. 도 이 처리되기를 기다리므로 남은 간선을 제거할 시작점이 없습니다. 처리한 정점 수는 이고 전체는 이므로 사이클이 있다고 판정합니다.
처리되지 않은 정점이 모두 사이클에 속하는 것은 아닙니다. 그림의 는 사이클에 속하지 않지만, 처리되지 않은 에서 간선이 들어오므로 함께 남습니다. 이 방법으로는 사이클의 존재를 판별하며, 사이클을 이루는 정점 목록을 바로 얻는 것은 아닙니다.
반대로 사이클이 없는 유한 방향 그래프에는 진입 차수가 인 정점이 존재합니다. 그런 정점이 없다고 가정하고 선행 정점을 계속 따라가면 결국 같은 정점을 다시 만나 사이클이 생기기 때문입니다. 따라서 사이클이 없다면 정점을 제거한 뒤에도 다음 후보가 존재하여 모든 정점을 처리할 수 있습니다.
복잡도
정점 수를 , 간선 수를 라고 합니다.
| 연산 | 시간복잡도 | 공간복잡도 |
|---|---|---|
| 일반 큐 위상 정렬 | 그래프 , 추가 | |
| 최소 우선순위 큐 위상 정렬 | 그래프 , 추가 |
예제
문제
각 작업의 선행 관계가 주어진다. 가능한 작업 중 번호가 가장 작은 작업을 매번 선택하여 전체 작업 순서를 구하여라.
입력
첫째 줄에 작업 수 과 선행 관계 수 이 공백을 사이에 두고 주어진다. ; 이다.
다음 개 줄에 작업 번호 가 공백을 사이에 두고 주어진다. 이다. 작업 를 시작하려면 작업 를 먼저 마쳐야 한다.
출력
모든 작업을 수행할 수 있으면 작업 번호를 수행 순서대로 한 줄에 공백을 사이에 두고 출력한다. 수행할 수 없으면 IMPOSSIBLE을 출력한다.