[백준] 2252: 줄 세우기 (feat.위상정렬)

2022. 5. 4. 09:42TIL💡/Algorithms

https://www.acmicpc.net/problem/2252

 

2252번: 줄 세우기

첫째 줄에 N(1 ≤ N ≤ 32,000), M(1 ≤ M ≤ 100,000)이 주어진다. M은 키를 비교한 회수이다. 다음 M개의 줄에는 키를 비교한 두 학생의 번호 A, B가 주어진다. 이는 학생 A가 학생 B의 앞에 서야 한다는 의

www.acmicpc.net

 

위상정렬(Topology Sort)는 순서(선후)가 정해져 있는 작업을 차례로 수행해야 할 때 그 순서를 사용하는 알고리즘이다.

 

위상 정렬은 여러 개의 답이 존재할 수 있다.

또한 위상 정렬은 DAG(Directed Acyclic Graph)에만 적용이 가능하다. 사이클이 발생하는 경우에는 위상 정렬을 수행할 수 없다.

위상 정렬은 시작점이 존재해야 하는데, 사이클에서는 시작점을 찾을 수 없기 때문이다.

 

Queue를 사용한 위상정렬 알고리즘

  1. 진입차수가 0인 정점을 Queue에 삽입한다.
  2. Queue에서 원소를 꺼내 연결된 모든 간선을 제거한다.(진입차수 감소)
  3. 간선 제거 이후에 진입차수가 0이 된 정점을 Queue에 삽입한다.
  4. Queue가 빌 때까지 2~3번을 반복한다. 모든 원소를 방문하기 전에 Queue가 빈다면 사이클이 존재하는 것이고, 모든 원소르 ㄹ방문했다면 Queue에서 꺼낸 순서가 위상 정렬의 결과이다.
#include <iostream>
#include <vector>
#include <utility>
#include <queue>
using namespace std;
vector<vector<int>> students(32001);
vector<int> indegree(32001, 0);
queue<int> q;
vector<int> result;
int main(void) {
    int n, m, a, b;
    cin >> n >> m;
    for(int i =0;i < m;i++) {
        cin >> a >> b;
        indegree[b]++;
        students[a].push_back(b);
    }

    for(int i = 1;i <= n;i++) {
        if (!indegree[i]) q.push(i);
    }

    for(int i = 1;i <= n;i++){
        if(q.empty()) {
            // 사이클 발생
            return 0;
        }
        int num = q.front();
        q.pop();
        result.push_back(num);
        for(auto j : students[num]) {
            if(--indegree[j] == 0) {
                q.push(j);
            }
        }
    }

    for(auto r: result) {
        cout << r << " ";
    }
}

 

참고

https://m.blog.naver.com/ndb796/221236874984

 

25. 위상 정렬(Topology Sort)

위상 정렬(Topology Sort)은 '순서가 정해져있는 작업'을 차례로 수행해야 할 때 그 순서를 결정해주기 ...

blog.naver.com

 

'TIL💡 > Algorithms' 카테고리의 다른 글

[백준] 16472: 고냥이  (0) 2022.05.04
[백준] 1005: ACM Craft  (0) 2022.05.04
[백준] 5430: AC  (0) 2022.05.03
C++로 코딩테스트를 풀 때 추가하는 구문의 목적  (0) 2022.05.03
최단 경로 문제  (0) 2022.05.02