득이공간

[백준 C++] 2252 줄 세우기 - 위상정렬 본문

PS/알고리즘 문제풀이

[백준 C++] 2252 줄 세우기 - 위상정렬

쟁득 2024. 2. 1. 20:11
 

2252번: 줄 세우기

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

www.acmicpc.net

cpp
#include <iostream> #include <vector> #include <list> #include <queue> using namespace std; vector<list<int>> Neighbors; vector<int> Entries; vector<int> Sequence; queue<int> SearchQueue; int main() { ‌ios::sync_with_stdio(false); ‌cin.tie(NULL); ‌cout.tie(NULL); int N, M; ‌cin >> N >> M; ‌Neighbors.reserve(N); for (int i = 0; i < N; ++i) { ‌‌Neighbors.emplace_back(list<int>()); } ‌Entries.reserve(N); for (int i = 0; i < N; ++i) { ‌‌Entries.emplace_back(0); } for (int i = 0; i < M; ++i) { ‌‌int A, B; ‌‌cin >> A >> B; ‌‌Neighbors[A - 1].emplace_back(B - 1); ‌‌++Entries[B - 1]; } int i = 0; for (int& Entry : Entries) { ‌‌if (Entry == 0) ‌‌{ ‌‌‌SearchQueue.push(i); ‌‌} ‌‌++i; } ‌Sequence.reserve(N); while (!SearchQueue.empty()) { ‌‌int Current = SearchQueue.front(); ‌‌SearchQueue.pop(); ‌‌Sequence.emplace_back(Current); ‌‌for (const int& Neighbor : Neighbors[Current]) ‌‌{ ‌‌‌--Entries[Neighbor]; ‌‌‌if (Entries[Neighbor] == 0) ‌‌‌{ ‌‌‌‌SearchQueue.push(Neighbor); ‌‌‌} ‌‌} } for(const int& Student : Sequence) { ‌‌cout << Student + 1 << ' '; } }

해당 문제는 사이클이 없는 방향 그래프에서 노드 순서를 찾는 문제로

위상 정렬 알고리즘을 사용해서 다음과 같은 단계로 풀었습니다.

 

1. 인접 리스트를 통해서 진입차수 계산

2. 진입 차수가 0인 미방문 노드 선택 후 위상 정렬 배열에 추가

3. 해당 노드의 인접 노드들의 진입 차수 업데이트

4. 모든 노드가 위상 정렬 배열에 추가될 때까지 2~3번 반복