문제
https://www.acmicpc.net/problem/2252
문제 요약
N명의 학생들을 키 순서대로 줄을 세우려고 한다.
각 학생의 키가 주어지지 않고, 두 학생의 키를 비교 결과가 M개 주어졌을 때 줄을 세우는 방법을 출력한다.
답이 여러 가지인 경우 아무거나 출력한다.
코드
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <tuple>
#include <queue>
using namespace std;
int N, M;
vector<int> edges[32032];
// indegree[i]: i번 노드로 들어오는 간선의 수
int indegree[32032];
queue<int> q;
int main() {
cin >> N >> M;
// 그래프 입력
while (M--) {
// a번 학생이 a번 학생보다 앞에 있다.
int a, b;
cin >> a >> b;
edges[a].push_back(b);
indegree[b]++;
}
// 초기 indegree가 0인 값부터
for (int i = 1; i <= N; i++) {
if (indegree[i] == 0) {
q.push(i);
}
}
while (!q.empty()) {
int x = q.front();
cout << x << " ";
q.pop();
for (int i = 0; i < edges[x].size(); i++) {
int y = edges[x][i];
indegree[y]--;
if (indegree[y] == 0) {
q.push(y);
}
}
}
return 0;
}
코드 설명
위상 정렬(Topological Sort)을 이용해 문제를 해결한다.
위상 정렬이란 사이클이 없는 방향 그래프에서 각 노드가 하나의 일이라고 생각했을 때, 앞에 일이 끝나야만 뒤에 일이 진행될 수 있는 문제에서 가능한 노드의 순서를 뽑는 방법이다.
이 때, 가능한 순서는 유일하지 않다.
1. i번 노드에 들어오는 간선의 개수를 저장하는 indegree[i]를 정의한다.
2. vector 배열 edges에 그래프 정보를 인접 리스트 형태로 입력 받는다.
+ 이 때, indegree를 증가시키며 초기 값을 설정한다.
3. 처음 indegree가 0인 값들을 큐에 넣는다.
4. 큐가 빌 때까지 원소를 하나씩 빼면서, 해당 원소(노드)와 인접한 노드의 간선을 제거한다.
+ indegree 값을 감소시키면, 간선 하나가 제거된 것과 같다.
5. 원소가 POP되는 순서가 위상 정렬 순서이다.
고찰
문제를 보고 그래프를 이용한 문제까지는 생각했지만, 위상정렬을 생각하기는 어려웠다..
관련 문제를 좀 더 풀어봐야겠다.
아래 코드는 Greedy로 시도한 코드이다.. (실패)
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <tuple>
#include <queue>
using namespace std;
// arr[i]: i번 학생의 줄 위치
int student[32032];
int N, M;
// q[i]: { i번 학생의 줄 위치. i }
priority_queue<tuple<int, int>> q;
int main() {
cin >> N >> M;
// 초기 줄 : 1, 2, 3, 4, ...
for (int i = 1; i <= N; i++) {
student[i] = i;
}
while (M--) {
// A번 학생이 B번 학생보다 앞에 있다.
int A, B;
cin >> A >> B;
// 이미 A번 학생이 B번 학생보다 앞에 있는 경우
if (student[A] < student[B]) continue;
swap(student[A], student[B]);
for (int i = 1; i <= N; i++) {
cout << student[i] << " ";
}
cout << "\n";
}
for (int i = 1; i <= N; i++) {
q.push({ -student[i], i });
}
while (!q.empty()) {
int stu_i, i;
tie(stu_i, i) = q.top();
q.pop();
cout << i << " ";
}
return 0;
}
'Algorithm Problems > 그래프' 카테고리의 다른 글
[백준/C++] 11404번: 플로이드 (0) | 2024.07.15 |
---|---|
[백준/C++] 2206번: 벽 부수고 이동하기 (0) | 2024.07.14 |
[백준/C++] 7576번: 토마토 (1) | 2024.05.17 |
[백준/C++] 13565번: 침투 (0) | 2024.05.05 |
[백준/C++] 16562번: 친구비 (0) | 2024.04.16 |