본문 바로가기
Algorithm/Graph Search Algorithm

BOJ G4 1504 특정한 최단 경로 JAVA

by rueMi 2024. 1. 21.

 

1504번: 특정한 최단 경로

첫째 줄에 정점의 개수 N과 간선의 개수 E가 주어진다. (2 ≤ N ≤ 800, 0 ≤ E ≤ 200,000) 둘째 줄부터 E개의 줄에 걸쳐서 세 개의 정수 a, b, c가 주어지는데, a번 정점에서 b번 정점까지 양방향 길이 존

www.acmicpc.net


문제 읽기

방향성이 없는 그래프가 주어진다. 양방향이어도 다익스트라를 사용하는 데에는 전혀 문제가 없고, 단지 처음에 그래프를 인접 리스트로 입력 받을 때, 양 쪽에 다 넣어주면 된다.

 

일단 이 문제에서는 주어지는 두 노드를 반드시 방문하면서 1 → N까지의 최소 거리를 구해야 한다.

 

즉, 주어지는 두 노드를 mid1, mid2라고 한다면,

1 → mid1 → mid2 → N

또는

1 → mid2 → mid1 → N

 

이 두 경우만 고려하면 된다.


문제 풀기

두 경우에 따라 최종 결과를 구하는 식은 다음과 같다.

//1 -> mid1 -> mid2 -> N
ans1 = dist(1, mid1) + dist(mid1, mid2) + dist(mid2, N); 
//1 -> mid2 -> mid1 -> N
ans1 = dist(1, mid2) + dist(mid2, mid1) + dist(mid1, N); 

 

여기서

 

dist(1, mid1), dist(1, mid2)는 dijkstra(start=1)의 결과로 구할 수 있고,

dist(mid1, mid2) == dist(mid2, mi1)은 양방향 그래프이므로 값이 같기 때문에 dijkstra(start=mid1 or mid2)로 구할 수 있다.

마지막으로 dist(mid2, N) == dist(N, mid2), dist(mid1, N) == dist(N, mid1)이므로 dijkstra(start = N)으로 구할 수 있다.

 

그래서 나는 다익스트라를 3번만 사용했다.

  1. 1을 출발점으로 다익스트라 1번,
  2. mid1을 출발점으로 다익스트라 1번,
  3. N을 출발점으로 다익스트라 1번

실수한 부분

INF 값의 설정

내가 푼 풀이 방식은 마지막에 dijkstra값을 세 번 더해줘야 한다. 따라서 dist의 초기 값인 INF가 너무 크면.. 오버플로우가 발생한다.

이것 때문에 8X퍼에서 계속 틀리다가 INF 값을 조정해주니까 통과됐다.

 

처음에는 INF를 Integer.MAX_VALUE - 1001로 했다가,

간선의 개수 E X 거리 c = 200,000 X 1,000 = 200000000로 했더니 통과되었다.


코드

package ps.ㄱSolving;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class BOJ_G4_1504_특정한_최단경로 {
    static class Node{
        int no;
        int cost;
        public Node(int no, int cost){
            this.no = no;
            this.cost = cost;
        }
    }
    static int N, E;
    static ArrayList<Node>[] graph;
    static int mid1, mid2;
    static int[][] dist;
    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(in.readLine());
        N = Integer.parseInt(st.nextToken());
        E = Integer.parseInt(st.nextToken());
        graph = new ArrayList[N+1]; //1~N
        for (int i = 0; i < N+1; i++){
            graph[i] = new ArrayList<>();
        }
        while(E-- > 0){
            st = new StringTokenizer(in.readLine());
            int start = Integer.parseInt(st.nextToken());
            int end = Integer.parseInt(st.nextToken());
            int cost = Integer.parseInt(st.nextToken());
            graph[start].add(new Node(end, cost));
            graph[end].add(new Node(start, cost)); //양방향
        }
        st = new StringTokenizer(in.readLine());
        mid1 = Integer.parseInt(st.nextToken());
        mid2 = Integer.parseInt(st.nextToken());

        //logic : dijkstra 3번
        dist = new int[3][N+1];
        dijkstra(1, 0);
        dijkstra(mid1, 1);
        dijkstra(N, 2);

        //print
        long ans1 = dist[0][mid1] + dist[1][mid2] + dist[2][mid2]; //1 -> mid1 -> mid2 -> N
        long ans2 = dist[0][mid2] + dist[1][mid2] + dist[2][mid1]; //1 -> mid2 -> mid1 -> N
        if (ans1 >= INF && ans2 >= INF) System.out.println("-1");
        else System.out.println((ans1 > ans2)? ans2 : ans1);
    }

    static int INF = 200000000; //2억
    private static void dijkstra(int start, int i) {
        //pq, visited
        PriorityQueue<Node> pq = new PriorityQueue<>(new Comparator<Node>() {
            @Override
            public int compare(Node o1, Node o2) {
                return o1.cost - o2.cost;
            }
        });
        boolean[] visited = new boolean[N+1];

        //init
        Arrays.fill(dist[i], INF);
        dist[i][start] = 0;
        pq.offer(new Node(start, 0));

        while(!pq.isEmpty()){
            Node cur = pq.poll();
            if (visited[cur.no]) continue;
            visited[cur.no] = true;

            for (Node adj : graph[cur.no]){
                if (dist[i][adj.no] > dist[i][cur.no] + adj.cost){
                    dist[i][adj.no] = dist[i][cur.no] + adj.cost;
                    pq.offer(new Node(adj.no, dist[i][adj.no]));
                }
            }
        }
    }
}

의문점..

 

글 읽기 - 1504 특정한 최단경로 INF 값 정하기

댓글을 작성하려면 로그인해야 합니다.

www.acmicpc.net

위 글을 보고 INF 값을 800000으로 해서 제출했는데 60퍼에서 틀린다. 2억으로 하면 맞다. 왜지..???

'Algorithm > Graph Search Algorithm' 카테고리의 다른 글

BOJ G4 1261 알고스팟 JAVA  (0) 2024.01.22
0-1 BFS  (0) 2024.01.22
BOJ G3 1238 파티 JAVA  (0) 2024.01.20
BOJ G5 1916 최소비용구하기 JAVA  (0) 2024.01.20
다익스트라, Dijkstra Algorithm  (0) 2024.01.20