반응형
01-23 05:39
Today
Total
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
관리 메뉴

개발하는 고라니

[백준] 18352번 : 특정 거리의 도시 찾기 본문

Programming/백준

[백준] 18352번 : 특정 거리의 도시 찾기

조용한고라니 2021. 2. 4. 18:15
반응형
 

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

# 문제

어떤 나라에는 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을 출력한다.

# 예제 입력

4 4 2 1

1 2

1 3

2 3

2 4

# 예제 출력

4


[다익스트라 + 큐]

기본적인 다익스트라 알고리즘을 사용하되 우선 순위큐를 사용한다면 시간 초과가 발생한다. 우선순위 큐는 힙구조를 유지하기 때문에 큐와 비교했을 때 시간 복잡도가 더 느리기 때문이다. 모든 간선의 가중치가 다르다면 우선순위 큐를 사용함이 올바르지만, 이 문제는 모든 간선의 가중치는 1이기 때문에 굳이 우선순위 큐를 사용할 필요가 없다.

 

그리고 시간과 메모리를 조금 더 아끼고 싶다면, 큐에서 꺼냇을 때 거리가 k 이상이면 continue 해주면 더 빠르게 동작한다.

        while(!Q.isEmpty()){//다익스트라의 일부
            Edge edge = Q.poll();
            int current = edge.tg;
            int d = edge.d;

            if(distance[current] < d || d > k) continue; //k보다 크면 스킵

            for(Edge e:list[current]){
                int next = e.tg;
                int nextD = d + e.d;

                if(distance[next] > nextD){
                    distance[next] = nextD;
                    Q.add(new Edge(next, nextD));
                }
            }
        }

# Code </>

public class Main {

    static class Edge{
        int tg, d;
        public Edge(int t, int dist){
            tg=t; d=dist;
        }
    }
    static final int INF = 1000000000;
    static int n, m, k;
    static int[] distance = new int[300001];
    static List<Edge>[] list = new ArrayList[300001];

    static void Dijkstra(int start){
        Queue<Edge> Q = new LinkedList<>();

        distance[start] = 0;
        Q.add(new Edge(start, 0));

        while(!Q.isEmpty()){
            Edge edge = Q.poll();
            int current = edge.tg;
            int d = edge.d;

            if(distance[current] < d || d > k) continue;

            for(Edge e:list[current]){
                int next = e.tg;
                int nextD = d + e.d;

                if(distance[next] > nextD){
                    distance[next] = nextD;
                    Q.add(new Edge(next, nextD));
                }
            }
        }
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        List<Integer> l = new ArrayList<>();

        n = Integer.parseInt(st.nextToken());
        m = Integer.parseInt(st.nextToken());
        k = Integer.parseInt(st.nextToken());
        int x = Integer.parseInt(st.nextToken());

        for(int i=1; i<=n; i++){
            list[i] = new ArrayList<>();
            distance[i] = INF;
        }

        for(int i=0; i<m; i++){
            st = new StringTokenizer(br.readLine());
            list[Integer.parseInt(st.nextToken())].add(new Edge(Integer.parseInt(st.nextToken()), 1));
        }

        Dijkstra(x);

        for(int i=1; i<=n; i++)
            if(distance[i] == k) l.add(i);
        Collections.sort(l);

        if(l.size() == 0) System.out.println(-1);
        else
            for(int a : l)
                System.out.println(a);

    }
}
반응형
Comments