🔗 2252번 : 줄 세우기
● Java 풀이
● 시간 제한 2초
● 메모리 제한 128 MB
문제
N명의 학생들을 키 순서대로 줄을 세우려고 한다. 각 학생의 키를 직접 재서 정렬하면 간단하겠지만, 마땅한 방법이 없어서 두 학생의 키를 비교하는 방법을 사용하기로 하였다. 그나마도 모든 학생들을 다 비교해 본 것이 아니고, 일부 학생들의 키만을 비교해 보았다.
일부 학생들의 키를 비교한 결과가 주어졌을 때, 줄을 세우는 프로그램을 작성하시오.
테스트 케이스
/** 출처 (https://www.acmicpc.net/board/view/130776) **/
// input
9 10
1 3
2 3
2 4
2 5
3 6
3 7
4 7
5 7
6 8
7 8
// answer
1 2 3 4 5 6 7 8 9
// input
4 4
1 3
3 2
1 2
1 4
// answer
1 3 2 4
/** 출처 (https://www.acmicpc.net/board/view/74119) **/
// input
5 4
2 3
1 2
4 2
5 2
// answer
1 4 5 2 3
풀이
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
public class Main {
private static int N, M; // 학생 N명, 키 비교 횟수 M번
private static StringBuilder sb;
private static List<Integer>[] nodes;
private static boolean[] visited;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine());
sb = new StringBuilder();
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
nodes = new ArrayList[N + 1]; // 부모노드를 가리킬 리스트
visited = new boolean[N + 1]; // 방문 처리
int a, b; // 학생들을 임의로 저장할 변수 선언
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
a = Integer.parseInt(st.nextToken());
b = Integer.parseInt(st.nextToken());
if (nodes[b] == null) nodes[b] = new ArrayList<>();
nodes[b].add(a); // 자식 노드에 부모 노드 연결 (작은 사람이 우선순위 높음)
}
for (int i = 1; i <= N; i++) {
if (!visited[i]) { // 방문하지 않았을 경우
dfs(i); // 해당 경로로 거치는 모든 노드 DFS
//System.out.println(" 방문");
}
}
bw.append(sb.toString());
bw.flush();
bw.close();
br.close();
}
private static void dfs(int n) {
visited[n] = true;
if (nodes[n] != null) { // null일 경우 (루트노드일 경우) 바로 출력
for (int parent : nodes[n]) {
if (!visited[parent]) dfs(parent); // 부모 노드로 이동하는 DFS 재귀
}
}
sb.append(n).append(" "); // 제일 작은 노드부터 삽입
//System.out.print(n);
}
}
위상 정렬 문제. 이렇게 하나 또 배워 간다.
처음엔 우선순위를 누적 합으로 매기는 방식으로 풀었는데, 시간 초과가 났다.
문제에서 주는 테스트 케이스에서 1 → 3, 2 → 3을 출력하려면, 무조건 리프 노드부터 시작해야 한다고 생각해서 그래프 방식으로 풀지 않았었는데, 결국 서로 연결고리가 없는 자식 노드들은 순서를 아무렇게나 해도 상관없다는 뜻이 된다는 게 위상 정렬 방식으로 풀고 나니 알겠다.
'알고리즘 및 데이터 구조 > 백준' 카테고리의 다른 글
[백준] 11049번 : 행렬 곱셈 순서 (Java) (0) | 2024.02.23 |
---|---|
[백준] 9466번 : 텀 프로젝트 (Java) (0) | 2024.02.22 |
[백준] 14890번 : 경사로 (Java) (0) | 2024.02.20 |
[백준] 1005번 : ACM Craft (Java) (0) | 2024.02.19 |
[백준] 1520번 : 내리막 길 (Java) (0) | 2024.02.18 |