-
백준 1504번 특정한 최단 경로 (JAVA)알고리즘(Algorithm)/다익스트라(Dijkstra) 2022. 4. 15. 18:26
백준 1504번 특정한 최단 경로 (JAVA)
https://www.acmicpc.net/problem/1504
1504번: 특정한 최단 경로
첫째 줄에 정점의 개수 N과 간선의 개수 E가 주어진다. (2 ≤ N ≤ 800, 0 ≤ E ≤ 200,000) 둘째 줄부터 E개의 줄에 걸쳐서 세 개의 정수 a, b, c가 주어지는데, a번 정점에서 b번 정점까지 양방향 길이 존
www.acmicpc.net
문제
방향성이 없는 그래프가 주어진다. 세준이는 1번 정점에서 N번 정점으로 최단 거리로 이동하려고 한다. 또한 세준이는 두 가지 조건을 만족하면서 이동하는 특정한 최단 경로를 구하고 싶은데, 그것은 바로 임의로 주어진 두 정점은 반드시 통과해야 한다는 것이다.
세준이는 한번 이동했던 정점은 물론, 한번 이동했던 간선도 다시 이동할 수 있다. 하지만 반드시 최단 경로로 이동해야 한다는 사실에 주의하라. 1번 정점에서 N번 정점으로 이동할 때, 주어진 두 정점을 반드시 거치면서 최단 경로로 이동하는 프로그램을 작성하시오.
입력
첫째 줄에 정점의 개수 N과 간선의 개수 E가 주어진다. (2 ≤ N ≤ 800, 0 ≤ E ≤ 200,000) 둘째 줄부터 E개의 줄에 걸쳐서 세 개의 정수 a, b, c가 주어지는데, a번 정점에서 b번 정점까지 양방향 길이 존재하며, 그 거리가 c라는 뜻이다. (1 ≤ c ≤ 1,000) 다음 줄에는 반드시 거쳐야 하는 두 개의 서로 다른 정점 번호 v1과 v2가 주어진다. (v1 ≠ v2, v1 ≠ N, v2 ≠ 1) 임의의 두 정점 u와 v사이에는 간선이 최대 1개 존재한다.
출력
첫째 줄에 두 개의 정점을 지나는 최단 경로의 길이를 출력한다. 그러한 경로가 없을 때에는 -1을 출력한다.
소스 코드
- 다익스트라 문제
- 방향성이 없는 그래프 = 무방향(=양방향) 인접리스트 구성 필요
- cost 초기값인 INF 는 오버플로우 나지 않도록 200,000(E의 최대값) * 1,000(c의 최대값) 값으로 설정
- 목적지와, 목적지의 비용(거리)를 담는 Node class 생성하여 사용
- 경로는 크게 두 가지 : 1 → v1 → v2 → N와 1 → v2 → v1 → N
- 두 가지 경로 중 더 작은 값을 출력
- 이 때 두 경로 모두 INF와 같거나 INF보다 큰 값이 나오면 경로가 없다는 의미이기 때문에 -1 출력
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.PriorityQueue; import java.util.StringTokenizer; public class Main { private static int N, E, Ans; // N:정점, E:간선 private static int INF = 200000000; //200,000 * 1,000 private static ArrayList<Node>[] adjList; private static int[] cost; private static boolean[] visited; private static class Node implements Comparable<Node>{ int dest, cost; //dest: 목적지, cost: 거리 public Node(int dest, int cost){ this.dest = dest; this.cost = cost; } @Override public int compareTo(Node o){ return this.cost - o.cost; //cost 기준 오름차순 정렬 } } public static void main(String[] args) throws Exception{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); StringTokenizer st; Ans = 0; st = new StringTokenizer(br.readLine()); N = Integer.parseInt(st.nextToken()); E = Integer.parseInt(st.nextToken()); adjList = new ArrayList[N+1]; cost = new int[N+1]; visited = new boolean[N+1]; //인접리스트 초기화 for (int i = 0; i < N+1; i++) { adjList[i] = new ArrayList<>(); } for (int i = 0; i < E; i++) { st = new StringTokenizer(br.readLine()); int a = Integer.parseInt(st.nextToken()); //출발지 int b = Integer.parseInt(st.nextToken()); //도착지 int c = Integer.parseInt(st.nextToken()); //비용(거리) adjList[a].add(new Node(b, c));//단방향인 경우 이것만 해도 됨 adjList[b].add(new Node(a, c));//무방향(양방향)은 이것도 해야 함 } st = new StringTokenizer(br.readLine()); int v1 = Integer.parseInt(st.nextToken()); int v2 = Integer.parseInt(st.nextToken()); int ans1 = 0; // 1 > v1 > v2 > N ans1 += dijkstra(1, v1); ans1 += dijkstra(v1, v2); ans1 += dijkstra(v2, N); int ans2 = 0; // 1 > v2 > v1 > N ans2 += dijkstra(1, v2); ans2 += dijkstra(v2, v1); ans2 += dijkstra(v1, N); if(ans1 >= INF && ans2 >= INF) Ans = -1; //경로가 없는 경우 else Ans = Math.min(ans1, ans2); //경로가 있을 경우 더 작은 값 bw.write(Ans+"\n"); bw.flush(); bw.close(); br.close(); } private static int dijkstra(int start, int end){ //최저비용 기준 탐색경로 저장 위한 우선순위 큐 PriorityQueue<Node> pq = new PriorityQueue<>(); Arrays.fill(visited, false); //방문여부 체크 배열 false로 초기화 Arrays.fill(cost, INF); //cost 배열 INF로 초기화 cost[start] = 0; //시작점이기 때문에 거리 0으로 셋팅 pq.add(new Node(start, 0)); while (!pq.isEmpty()){ Node now = pq.poll(); if(visited[now.dest]) continue; //방문했던 정점이면 스킵 visited[now.dest] = true; //미방문이면 방문으로(true)로 셋팅하고 for문 처리 //간선 탐색 for (Node next:adjList[now.dest]) { if(cost[next.dest] > next.cost + now.cost){ cost[next.dest] = next.cost + now.cost; pq.add(new Node(next.dest, cost[next.dest])); } } } return cost[end]; //목적지 end 까지의 최단거리 } }
'알고리즘(Algorithm) > 다익스트라(Dijkstra)' 카테고리의 다른 글
백준 1238번 파티 (JAVA) (0) 2022.04.15 백준 1916번 최소비용 구하기(JAVA) (0) 2021.04.08 백준 1753번 최단경로 (JAVA) (0) 2021.04.07