Algorithm/Algorithm

[Algorithm] - 위상 정렬

Dortmoot 2022. 9. 1. 22:26

위상 정렬


방향 그래프에서 간선으로 주어진 정점 간 선후 관계를 위배하지 않도록 나열하는 정렬
싸이클이 존재하는 경우는 발생할 수 없다

 

  • 일반적으로 방향그래프로 설정이 되어 있기 때문에 Indegree 값이 0인 Node들에서 먼저 시작하면서 VFS 처럼 구현하면 된다.
  • 위상 정렬의 결과가 Node들의 수와 동일해야 한다! ( 동일하지 않는 경우는 Cycle이 발생된 경우 )

 

알고리즘

시간 복잡도 : O( V+E )

1. 처음 방향 그래프들의 Edge를 읽으며, Indegree Table을 설정

2. Indegree가 0인 Node들을 Queue에 넣는다.

3. Queue에 Node들을 꺼내며, 위상 정렬 값 추가

4. 연결된 Node들의 Indgree값을 줄여주고 , 0이면 Queue에 추가

5. 3~4반복

# 위상 정렬
# 그래프를 사용
# Indgree의 값을 보고 판단
'''
7 7
A B
D B
C B
C D
D E
E F
G E
'''
import sys
from collections import deque
input = sys.stdin.readline

n , m = map ( int , input().split() )
adj = [ [] for _ in range( m ) ]
indgree = [0]*m
queue = deque()
answer = []

for _ in range( n ) :
    start , end = map ( str , input().split() )
    adj[ord(start)-65].append(ord(end)-65)
    indgree[ord(end)-65] += 1

for index , graph in enumerate(indgree) :
    if not graph :
        queue.append(index)

while ( queue ) :
    temp = queue.popleft()
    answer.append(chr(temp+65))
    for data in adj[temp] :
        indgree[data] -= 1
        if not indgree[data] :
            queue.append(data)

print (answer)

 

BOJ 2252번 - 줄 세우기


  • 선후관계 처리가 필요함에 따라 위상 정렬로 풀어야 한다.
# BOJ 2252번 - 줄 세우기
# Idea - 두 학생의 키를 보고 정렬 시켜야 한다.
# Edge = 선후 관계 -> 위상 정렬

import sys
from collections import deque
input = sys.stdin.readline

n , m = map( int , input().split() )
adj = [[] for _ in range( n+1 )]
indegree = [0] * (n+1)
queue = deque()
answer = []

for _ in range( m ) :
    small , big = map ( int , input().split() )
    adj[small].append(big)
    indegree[big] += 1

for index , data in enumerate ( indegree[1:] ) :
    if not data :
        queue.append(index+1)

while ( queue ) :
    temp = queue.popleft()
    answer.append(temp)
    for data in adj[temp] :
        indegree[data] -= 1
        if not indegree[data] :
            queue.append(data)
    
[print(temp) for temp in answer]

 

프로그래머스 - 순위


  • 위상정렬 문제인듯 보이지만, 단순 그래프 구현 문제이다.