반응형
백준 18352번 문제 - 특정 거리의 도시 찾기
18352번: 특정 거리의 도시 찾기
첫째 줄에 도시의 개수 N, 도로의 개수 M, 거리 정보 K, 출발 도시의 번호 X가 주어진다. (2 ≤ N ≤ 300,000, 1 ≤ M ≤ 1,000,000, 1 ≤ K ≤ 300,000, 1 ≤ X ≤ N) 둘째 줄부터 M개의 줄에 걸쳐서 두 개
www.acmicpc.net
문제 분석
- 도시의 개수 N, 도로의 개수 M, 거리 정보 K, 출발 도시의 번호 X를 입력 받고, M개의 도로가 어떻게 이뤄져있는지 입력받는다.
- 이를 토대로, X에서 출발했을 때 어떤 도시까지 갈 때 최단 거리가 K번인 도시들을 출력해라 (오름차순으로)
- 만약 그런 도시가 없을 경우, -1 출력
해결 키 포인트
- BFS(너비 우선 탐색) 개념 파악
- 오름차순 출력을 위해, Arrays.sort 이용
- 현재 BFS로 확인했을 때, 깊이 정도가 K와 동일할 경우 queue에 남은 값을 List에 담는다
- Arrays.sort로 오름차순 정렬한다
- 이때, PriorityQueue를 사용하면 안되는 이유는 큐 순서가 뒤죽박죽이 되서 너비 탐색이 제대로 일어나지 않기 때문이다
너비 우선 탐색(BFS)
그래프 완전 탐색 기번 중 하나로, 그래프의 시작 노드에서 출발해 시작 노드를 기준으로 가까운 노드를 먼저 방문하면서 탐색하는 알고리즘이다.
너비 우선 탐색의 핵심 이론
- 한번 방문한 노드를 다시 방문하면 안되므로 노드 방문 여부를 체크할 배열이 필요
- 그래프는 인접 리스트로 표현
- DFS의 탐색 방식은 선입 선출 특성을 가짐 ( 큐 사용 )
알고리즘
1. BFS를 시작할 노드를 정한 후 사용할 자료구조 초기화

2. 큐에서 노드를 꺼낸 후 꺼낸 노드의 인접 노드를 다시 큐에 삽입 (이를 모든 정점에 다한다)

만약 큐에 노드가 없으면, 방문하지 않은 정점을 알아내, 큐에 삽입하고 다시 2번 단계를 반복한다.
코드
import java.io.*;
import java.util.*;
public class Main {
static BufferedWriter bw;
static ArrayList<Integer> [] lists;
static boolean [] isChecked;
static int N,K;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
bw = new BufferedWriter(new OutputStreamWriter(System.out));
// 입력
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());
int X = Integer.parseInt(st.nextToken());
// N개의 도시 초기화
lists = new ArrayList [N];
isChecked = new boolean[N];
for(int i=0;i<N;i++) {
lists[i] = new ArrayList<>();
}
// M개의 도로 입력
for(int i=0;i<M;i++) {
st = new StringTokenizer(br.readLine());
int start = Integer.parseInt(st.nextToken());
int end = Integer.parseInt(st.nextToken());
lists[start-1].add(end-1);
}
// bfs 실행
bfs(X-1);
bw.flush();
bw.close();
}
public static void bfs(int x) throws IOException {
Queue<Integer> queue = new LinkedList<>();
// 시작 인덱스 초기화
queue.add(x);
isChecked[x] = true;
// count 세기
int count = 0;
// queue에 담겨진게 없을 때까지
while(!queue.isEmpty()) {
// 현재 queue 사이즈만큼 queue에서 index를 알아내, 해당 index와 연결된 도시들을 queue에 추가
int queueSize = queue.size();
for(int i=0;i<queueSize;i++) {
ArrayList<Integer> list = lists[queue.poll()];
for(int j=0;j<list.size();j++) {
// 해당 index와 연결된 도시들을 queue에 추가
int newIndex = list.get(j);
if(!isChecked[newIndex]) {
isChecked[newIndex] = true;
queue.add(newIndex);
}
}
}
// count 증가 후, 비교를 통해 원하는 이동 값과 동일해질 경우 break
count++;
if(count == K) {
break;
}
}
// 만약, count가 동일하고 큐가 비어있지 않으면 해당 값들 출력
if(count == K && !queue.isEmpty()) {
int [] outputs = new int[queue.size()];
for(int i=0;i<outputs.length;i++) {
outputs[i] = queue.poll();
}
// 정렬해서 오름차순으로 출력
Arrays.sort(outputs);
for(int i=0;i<outputs.length;i++) {
bw.write(outputs[i]+1 + "\n");
}
}
// 그렇지 않으면 -1 출력
else {
bw.write(-1 + "\n");
}
}
}
반응형
'CodingTEST' 카테고리의 다른 글
[백준 1707] 이분 그래프 (JAVA) (0) | 2023.08.24 |
---|---|
[백준 1325] 효율적인 해킹 (JAVA) (0) | 2023.08.23 |
[백준 1033] 칵테일 (JAVA) (0) | 2023.08.17 |
[백준 1850] 최대공약수 (JAVA) (0) | 2023.08.17 |
[백준 1934] 최소공배수 (JAVA) (0) | 2023.08.17 |