Skip to content

Commit

Permalink
✍️ create: baekjoon 2252
Browse files Browse the repository at this point in the history
- 백준 2252번 문제 해설
  • Loading branch information
marunemo committed Dec 19, 2023
1 parent beabb65 commit 3f2b928
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 59 deletions.
Binary file added assets/screenshots/b2252.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 0 additions & 18 deletions code/b1402.cpp

This file was deleted.

41 changes: 0 additions & 41 deletions code/b2252.cpp

This file was deleted.

137 changes: 137 additions & 0 deletions pps/b2252.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
---
title: 백준 2252 | 줄 세우기
level: GOLD III
layout: default
parent: 문제 풀이
---
{% assign title = page.title | split: " | " %}
{% assign name = title[0] %}
{% assign title = title[1] %}
{% assign number = name | split: " " %}
{% assign number = number[1] %}

# **{{ title }}**
{: .no_toc .fs-9 }

{{ name }}
{: .fs-4 .d-inline }

{% if page.level contains 'BRONZE' %}
{{ page.level }}
{: .label .label-bronze }
{% elsif page.level contains 'SILVER' %}
{{ page.level }}
{: .label .label-silver }
{% elsif page.level contains 'GOLD' %}
{{ page.level }}
{: .label .label-gold }
{% elsif page.level contains 'PLATINUM' %}
{{ page.level }}
{: .label .label-platinum }
{% endif %}

<br/>

1. TOC
{:toc}

---

## 문제 내용
{: .fw-700 }

![problem.png](../assets/screenshots/b{{ number }}.png)

#### [문제 링크](https://www.acmicpc.net/problem/{{ number }})
{: .no_toc .fs-4 }

## 해결 방안
{: .fw-700 }

<div class="code-example" markdown="1">
문제에 따르면, N명의 학생들 중 일부 학생들에 대하여 학생 두 명씩 줄을 서는 순서만이 주어진 상태이다.
간단히 말하자면, 첫째 줄을 제외한 임의의 줄에서 A B라는 정보가 주어지면, 줄을 설 때 A가 B의 앞에만 있으면 된다.
결과적으로 **임의의 줄에서 나타난 순서에 위배만 되지 않는다면 순서를 어떻게 세우든 상관없다**.
각각 두 학생들 사이에 방향성이 있고 줄에 순환이 없으므로, 이 문제는 위상 정렬로 풀 수 있다.
{: .mb-1 }

먼저, 위상 정렬을 위해 각 학생들의 앞에 나와야 하는 학생들의 수를 확인한다.
그리고, 앞에 나오는 다른 학생들이 없는 학생들을 먼저 앞에 세운다.
각 학생들이 앞에 나오면, 해당 학생들 뒤에 나와야 하는 학생들을 이어서 세운다.
이 과정을 반복하면, 주어진 순서 정보를 따르는 방향으로 학생들이 정렬된다.
{: .mt-1 }

{: .note-title }
> 위상 정렬(topological sort)이란?
>
> 유향 비순환 그래프(Directed Acyclic Graph; DAG)의 방향성을 따라 순서대로 배열하는 정렬 방식이다.
> 다양한 정렬 알고리즘이 존재하지만, 대표적으로 Kahn's algorithm(for topological sort)이 있다.
>
> Kahn's algorithm의 순서는 다음과 같다.
> 1. 각 노드로 향하는 간선의 개수를 조사하여, 노드로 향하는 간선의 개수가 0인 노드들을 찾는다.
> 2. 찾은 노드들을 하나씩 꺼내, 해당 노드의 간선들이 가리키는 노드의 간선의 개수를 하나씩 줄인다.
> 3. 만약 노드로 향하는 간선의 개수가 0인 노드가 발생하면, 해당 노드도 찾은 노드 목록에 추가한다.
> 4. 모든 노드들을 찾아 간선들을 확인할 때까지 이 과정을 반복한다.
{: .note-title }
> 유향 비순환 그래프(Directed Acyclic Graph)이란?
>
> 유향 비순환 그래프(Directed Acyclic Graph; DAG)는 풀어서 설명하자면, 방향이 있고 순환하지 않는 그래프이다.
> 노드와 노드 사이의 간선에 방향성이 있어, 해당 방향성을 위배하지 않는 선에서 두 노드가 이어져있다.
> 그리고 비순환이라는 말에서 알 수 있듯이, 이러한 방향을 따라갔을 때 어느 출발 지점으로 돌아오는 간선이 존재해서는 안 된다.
> 예로 들어 A에서 B를 향하는 간선(A→B)가 있다고 한다면, B에서 A로 이동하는 것은 방향성에 위배되기 때문에 불가능하다.
> 또한, (A→B)와 (B→C)라는 간선이 있을 때, (C→A)라는 간선은 순환(cycle)이 만들어지기 때문에 존재할 수 없다.
</div>
## 풀이 코드
{: .fw-700 }

```cpp
#include <iostream>
#include <vector>
#include <queue>

using namespace std;

int main() {
int n, m; // 학생들의 수와 순서쌍의 수
int a, b; // 학생들의 순서쌍
vector<vector<int>> table(n + 1); // 인덱스별 자신의 뒤에 나오는 학생 리스트
vector<int> priority(n + 1); // 인덱스별 자신의 앞에 나오는 학생들의 수
queue<int> q; // 앞에 서는 순서
int top; // 현재 줄을 서는 학생

cin >> n >> m;
for(int i = 0; i < m; i++) {
cin >> a >> b;
// 앞에 나오는 학생들이 뒤에 나오는 학생들의 명단을 가진다.
table[a].push_back(b);
// 뒤에 나오는 학생들은 자신의 앞에 나오는 학생들의 수를 기록한다.
priority[b]++;
}

// 자신의 앞에 서는 학생이 없는 학생들을 먼저 큐(queue)에 넣는다.
for(int i = 1; i <= n; i++) {
if(priority[i] == 0)
q.push(i);
}

while(!q.empty()) {
// 큐에서 나오는 순서대로 학생들을 출력한다.
top = q.front();
q.pop();
cout << top << ' ';

// 먼저 나온 학생들은 뒤에 나오는 학생들의 '앞에 나오는 학생 수'를 감소시킨다.
// '앞에 나오는 학생 수'가 0이 되면, 그 학생도 이어서 줄을 선다.
for(auto node: table[top]) {
priority[node]--;
if(priority[node] == 0)
q.push(node);
}
}
cout << endl;
return 0;
}
```
{: .lh-0 .fw-700 .fs-4 }

0 comments on commit 3f2b928

Please sign in to comment.