Coding Memo
Baekjoon #18352 특정 거리의 도시 찾기 본문
파스칼의 삼각형
https://www.acmicpc.net/problem/18352
문제
어떤 나라에는 1번부터 N번까지의 도시와 M개의 단방향 도로가 존재한다. 모든 도로의 거리는 1이다. 이 때 특정한 도시 X로부터 출발하여 도달할 수 있는 모든 도시 중에서, 최단 거리가 정확히 K인 모든 도시들의 번호를 출력하는 프로그램을 작성하시오. 또한 출발 도시 X에서 출발 도시 X로 가는 최단 거리는 항상 0이라고 가정한다. 예를 들어 N=4, K=2, X=1일 때 다음과 같이 그래프가 구성되어 있다고 가정하자. 이 때 1번 도시에서 출발하여 도달할 수 있는 도시 중에서, 최단 거리가 2인 도시는 4번 도시 뿐이다. 2번과 3번 도시의 경우, 최단 거리가 1이기 때문에 출력하지 않는다. |
입력
첫째 줄에 도시의 개수 N, 도로의 개수 M, 거리 정보 K, 출발 도시의 번호 X가 주어진다. (2 ≤ N ≤ 300,000, 1 ≤ M ≤ 1,000,000, 1 ≤ K ≤ 300,000, 1 ≤ X ≤ N) 둘째 줄부터 M개의 줄에 걸쳐서 두 개의 자연수 A, B가 공백을 기준으로 구분되어 주어진다. 이는 A번 도시에서 B번 도시로 이동하는 단방향 도로가 존재한다는 의미다. (1 ≤ A, B ≤ N) 단, A와 B는 서로 다른 자연수이다. |
출력
X로부터 출발하여 도달할 수 있는 도시 중에서, 최단 거리가 K인 모든 도시의 번호를 한 줄에 하나씩 오름차순으로 출력한다. 이 때 도달할 수 있는 도시 중에서, 최단 거리가 K인 도시가 하나도 존재하지 않으면 -1을 출력한다. |
처음은 최단거리라고 나오지말자 다익스트라를 떠올렸는데, 가중치가 모두 1인 것을 보고 상관없다고 판단했다.
그 다음으로는 dfs로 깊이(=거리)가 특정 값(k)까지만 탐색해서 그 노드를 정렬해서 출력하면 된다고 막연하게 생각하고 시작을 했다.
그러나 depth를 체크하는 방법을 생각하지 못하여 bfs로 결국 풀었다...
인접노드는 List로 구성하였고,
마지막 정렬은 단순히 TreeSet를 이용했다(...) // 써보고 싶었던게 크다.
TreeSet은 삽입(add)과 삭제가(remove)가 오래걸리는 대신 정렬하여 set를 유지하고 있기 때문에 간편했기 때문이다. (물론 시간은 더 잡아먹었을 것이다.)
특정 depth까지만 확인하고 break나 continue가 될 수 있다면 훨씬 더 좋은 코드가 될 것같다...
풀이
visited[start] = true; queue.offer(start); while (!queue.empty) { int p = queue.poll(); for (int adjV : list[p]) { if (!visited[adjV]) { visited[adjV] = true; queue.offer(adjV); dist[adjV] += dist[v] + 1; // 전 distance 에 가중치 1(상수 값)를 더하기 } } } |
전체 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class P18352 {
static StringBuilder sb = new StringBuilder();
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
TreeSet<Integer> set = new TreeSet<>();
List<Integer>[] graph;
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
int k = Integer.parseInt(st.nextToken());
int x = Integer.parseInt(st.nextToken());
graph = new ArrayList[n];
for (int i=0; i<graph.length; i++) {
graph[i] = new ArrayList<>();
}
for (int i=0; i<m; i++) {
st = new StringTokenizer(br.readLine());
graph[Integer.parseInt(st.nextToken()) - 1].add(Integer.parseInt(st.nextToken()) - 1);
}
boolean[] visited = new boolean[graph.length]; // default : false
Queue<Integer> queue = new LinkedList<>();
int[] shortest = new int[graph.length]; // default: 0
visited[x-1] = true;
queue.offer(x - 1);
// bfs
while(!queue.isEmpty()) {
int v = queue.poll();
for(int i=0; i<graph[v].size(); i++) {
int adjacentV = graph[v].get(i);
if (!visited[adjacentV]) {
visited[adjacentV] = true;
queue.offer(adjacentV);
shortest[adjacentV] += shortest[v] + 1;
}
}
}
for (int i=0; i<shortest.length; i++) {
if (shortest[i] == k) {
set.add(i+1);
}
}
for (int e : set) {
sb.append(e).append("\n");
}
System.out.println(set.size()==0 ? -1 : sb.toString().trim());
br.close();
}
}
'문제풀이 > BOJ' 카테고리의 다른 글
Baekjoon #2212 센서 (0) | 2022.02.09 |
---|---|
Baekjoon #4963 섬의 개수 (0) | 2022.02.04 |
Baekjoon #1541 잃어버린 괄호 (0) | 2022.01.28 |
Baekjoon #14719 빗물 (0) | 2022.01.25 |
Baekjoon #2504 괄호의 값 (0) | 2022.01.22 |