https://www.acmicpc.net/problem/1766
1766번: 문제집
첫째 줄에 문제의 수 N(1 ≤ N ≤ 32,000)과 먼저 푸는 것이 좋은 문제에 대한 정보의 개수 M(1 ≤ M ≤ 100,000)이 주어진다. 둘째 줄부터 M개의 줄에 걸쳐 두 정수의 순서쌍 A,B가 빈칸을 사이에 두고 주
www.acmicpc.net
1. 문제의 유형 및 이해
위상정렬
N 문제를 풀려고 한다. 각 문제는 난이도 순서로 출제되어 있다 (번호에 따라)
"먼저 푸는 문제" 가 있다는 것을 알게 되었다.
1. N개의 문제는 모두 풀어야 한다.
2. 먼저 푸는 것이 좋은 문제는 먼저 푸는 것이 좋은 문제를 풀어야 한다.
3. 가능하면 쉬운 문제를 풀어야 한다.
풀 문제의 순서를 정해주세요,
어떤 정해진 조건에 따라 순서를 정하는 문제입니다.
먼저 풀어야 되는 조건에 따라 선을 연결해주어 그래프 처럼 생각해보면 위상정렬 문제임을 알아차릴 수 있습니다.
2. 문제 접근 방법
문제에서 주어진 두가지 기준을 생각해봅시다.
- 먼저 푸는 것이 좋은 문제는 먼저 푸는 것이 좋은 문제를 풀어야 한다.
- 가능하면 쉬운 문제를 풀어야 한다.
이 두 가지 정렬기준을 놓고 보았을 때 두 정렬기준의 우선순위를 나눈다면 뭐가 우선이 되어야 할까요.
"가능하면 쉬운 것을 먼저 풀고 싶다" 근데 "먼저 풀 문제가 있따면 먼저 풀겠다" 가 맞는 기준이 됩니다.
조금 헷갈린다면, 한 페이지에 하나의 문제가 적혀있는 문제집을 위와 같은 순서로 푼다고 생각해봅시다.
1번 문제를 풀려고 하는 데 추천문제 10번이 적혀있고, 10번으로 갔더니 추천문제 7번이 적혀있습니다.
그럼 우리는 7번 문제를 풀고 10번 문제를 풀고 1번 문제를 풀게 됩니다. 이후에 우리가 풀어야 할 문제는 2번 문제가 됩니다.
즉, 먼저 풀어야 하는 작은 문제들에 대해서는 위상정렬로 문제를 풀도록 합니다. (inDegree를 사용)
그러한 "가능한 문제"들에 대해 쉬운 것을 먼저 풀 수 있도록 PriorityQueue를 통해 관리해줍니다.
이 문제는 두 가지 정렬 방법에 대해 잘 혼용해서 사용도록 했습니다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
ArrayList<Integer>[] graph = new ArrayList[N+1];
int[] inDegree = new int[N+1];
for (int i = 0; i < N + 1; i++) graph[i] = new ArrayList<>();
for(int i =0;i<M;i++){
st = new StringTokenizer(br.readLine());
int prev = Integer.parseInt(st.nextToken());
int target = Integer.parseInt(st.nextToken());
inDegree[target]++;
graph[prev].add(target);
}
PriorityQueue<Integer> problems = new PriorityQueue<>();
StringBuilder sb = new StringBuilder();
for(int i =1;i<N+1;i++){
if(inDegree[i] ==0){
problems.add(i);
}
}
while (!problems.isEmpty()) {
int cur = problems.poll();
sb.append(cur).append(' ');
for (int next : graph[cur]) {
inDegree[next]--;
if(inDegree[next] == 0){
problems.add(next);
}
}
}
System.out.println(sb);
}
}
'알고리즘 > 문제풀이' 카테고리의 다른 글
[백준] Q2623 음악 프로그램 JAVA (0) | 2022.03.01 |
---|---|
[백준] Q16946 벽 부수고 이동하기 4 JAVA (0) | 2022.02.19 |
[백준] Q1202 보석도둑 JAVA (0) | 2022.02.19 |
[백준] Q1007 벡터 매칭 Java (0) | 2022.02.12 |
[백준] Q13460 구슬탈출2 JAVA (0) | 2022.02.11 |