https://www.acmicpc.net/problem/1766
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
int inDegree[32001];
bool visit[32001];
vector<int> g[32001];
vector<int> ans;
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int n, m;
cin >> n >> m;
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
g[u].push_back(v);
inDegree[v]++;
}
priority_queue<int, vector<int>, greater<int>> q;
for (int i = 1; i <= n; i++) {
if (!inDegree[i]) {
q.push(i);
}
}
while (true) {
if(q.empty()) {
break;
}
int cur = q.top();
q.pop();
ans.push_back(cur);
for (int i = 0; i < g[cur].size(); i++) {
inDegree[g[cur][i]]--;
if (!inDegree[g[cur][i]] && find(ans.begin(), ans.end(), g[cur][i]) == ans.end()) {
q.push(g[cur][i]);
}
}
g[cur].clear();
}
for (int i = 0; i < ans.size(); i++) {
cout << ans[i] << " ";
}
return 0;
}
위상 정렬 문제이다.
다만 기본적인 위상 정렬과는 살짝 다르다. 이 문제의 3번 조건 때문이다.
3. 가능하면 쉬운 문제부터 풀어야 한다.
이 조건에 의해 문제를 풀 때는 가능한 문제 중 가장 작은 숫자의 문제부터 풀어야 한다. 이를 해결하기 위해 우선순위 큐를 사용하였다.
풀이
g[u].push_back(v);
inDegree[v]++;
문제의 순서를 입력받을 때 그래프에 해당 노드를 넣고, inDegree(해당 버텍스를 가리키는 버텍스의 수)를 계산해준다.
priority_queue<int, vector<int>, greater<int>> q;
for (int i = 1; i <= n; i++) {
if (!inDegree[i]) {
q.push(i);
}
}
inDegree가 없는 문제는 순서에 구애를 받지 않으므로 큐에 집어넣어 준다. 우선순위 큐에 넣으므로 가장 쉬운 문제부터 연산을 진행하게 된다.
while (true) {
if(q.empty()) {
break;
}
int cur = q.top();
q.pop();
ans.push_back(cur);
for (int i = 0; i < g[cur].size(); i++) {
inDegree[g[cur][i]]--;
if (!inDegree[g[cur][i]] && find(ans.begin(), ans.end(), g[cur][i]) == ans.end()) {
q.push(g[cur][i]);
}
}
g[cur].clear();
}
이후, 해당 문제를 풀면서 이를 정답 벡터에 넣고, 이를 빼면서 해당 문제 다음 풀 수 있는 문제들의 inDegree를 계산해준다. 연산 후 inDegree가 없게 되면 이제 해당 문제(g[cur][i])를 풀 자격이 생기므로 큐에 집어넣는다.
모든 연산 종료 후 정답 벡터를 순서대로 출력하면 답이 된다.
'Coding Test' 카테고리의 다른 글
백준 15961 회전 초밥 (0) | 2024.05.22 |
---|---|
백준 17073 나무 위의 빗물 (1) | 2024.05.21 |
백준 17609 회문 (1) | 2024.05.19 |
백준 2224 명제 증명 (0) | 2024.05.18 |
백준 2015 수들의 합 4 (0) | 2024.05.18 |