티스토리 뷰
https://www.acmicpc.net/problem/14567
문제
올해 Z대학 컴퓨터공학부에 새로 입학한 민욱이는 학부에 개설된 모든 전공과목을 듣고 졸업하려는 원대한 목표를 세웠다. 어떤 과목들은 선수과목이 있어 해당되는 모든 과목을 먼저 이수해야만 해당 과목을 이수할 수 있게 되어 있다. 공학인증을 포기할 수 없는 불쌍한 민욱이는 선수과목 조건을 반드시 지켜야만 한다. 민욱이는 선수과목 조건을 지킬 경우 각각의 전공과목을 언제 이수할 수 있는지 궁금해졌다. 계산을 편리하게 하기 위해 아래와 같이 조건을 간소화하여 계산하기로 하였다.
- 한 학기에 들을 수 있는 과목 수에는 제한이 없다.
- 모든 과목은 매 학기 항상 개설된다.
모든 과목에 대해 각 과목을 이수하려면 최소 몇 학기가 걸리는지 계산하는 프로그램을 작성하여라.
입력
첫 번째 줄에 과목의 수 N(1 ≤ N ≤ 1000)과 선수 조건의 수 M(0 ≤ M ≤ 500000)이 주어진다. 선수과목 조건은 M개의 줄에 걸쳐 한 줄에 정수 A B 형태로 주어진다. A번 과목이 B번 과목의 선수과목이다. A < B인 입력만 주어진다. (1 ≤ A < B ≤ N)
출력
1번 과목부터 N번 과목까지 차례대로 최소 몇 학기에 이수할 수 있는지를 한 줄에 공백으로 구분하여 출력한다.
2252번 위상 정렬의 기본적인 문제와 거의 동일하다.
대신 인덱스를 줄 세우는 것이 아닌 몇학기에 수업을 들을 수 있는지 구하는 문제다.
큐에 인덱스 하나만 넣는게 아니라, int[] 로 인덱스와 학기를 넣어야 한다.
처음부터 진입차수가 0인 원소는 1학기부터 들을 수 있으므로 1로 설정하고,
처음부터 진입차수가 0이 아니었던 원소는 이전에 연결된 원소의 학기 +1로 설정한다.
즉
위상 정렬 그래프가 아래와 같을 경우
1은 진입차수가 0이기 때문에 1학기에 들을 수 있고,
2는 (1의 학기) + 1 이므로 2학기,
3은 (2의 학기) + 1 이므로 3학기가 된다.
1 -> 2 -> 3
처음에는 출력할 StringBuilder에 "0 ".repeat(N)을 해서 일단 0으로 채우고,
큐에서 꺼낼 때마다 setCharAt을 통해 해당하는 값을 변경해줬는데,
int형식의 학기를 char형식으로 바꾸면서 오류가 생긴 건지 자꾸 틀렸다고 떴다. (테스트 케이스는 잘 됨..)
그래서 결과값을 저장할 result[] 배열을 따로 만들어 저장하고,
마지막에 append를 통해 출력값을 생성했다.
import java.util.*;
import java.io.*;
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()); // 선수 조건 수
StringBuilder sb = new StringBuilder();
int indegree[] = new int[N + 1];
ArrayList<Integer> list[] = new ArrayList[N + 1];
for(int i=1;i<=N;i++)
list[i] = new ArrayList<>();
for(int i=0;i<M;i++) {
st = new StringTokenizer(br.readLine());
int pre = Integer.parseInt(st.nextToken());
int next = Integer.parseInt(st.nextToken());
list[pre].add(next);
indegree[next]++;
}
// 인덱스, 학기
Queue<int[]> q = new LinkedList<>();
int result[] = new int[N];
for(int i=1;i<=N;i++)
if(indegree[i] == 0)
q.offer(new int[] {i, 1});
while(!q.isEmpty()) {
int arr[] = q.poll();
int idx = arr[0];
int semester = arr[1];
result[idx - 1] = semester;
for(int i : list[idx])
if(--indegree[i] == 0)
q.offer(new int[] {i, semester + 1});
}
for(int i=0;i<N;i++)
sb.append(result[i]).append(' ');
System.out.println(sb);
}
}
'algorithm > BOJ' 카테고리의 다른 글
[백준/BOJ] 1543번 문서 검색 자바 풀이 (0) | 2022.12.10 |
---|---|
[백준/BOJ] 1516번 게임 개발 자바 풀이 (0) | 2022.11.16 |
[백준/BOJ] 2252번 줄 세우기 자바 풀이 (0) | 2022.11.16 |
[백준/BOJ] 10816번 숫자 카드 2 자바 풀이 (0) | 2022.11.15 |
[백준/BOJ] 1920번 수 찾기 자바 풀이 (0) | 2022.11.15 |