-
[백준]1504: 특정한 최단경로(java)Algorithm/백준 2022. 4. 26. 21:36728x90
https://www.acmicpc.net/problem/1504
문제
방향성이 없는 그래프가 주어진다. 세준이는 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을 출력한다.
예제 입력 1
4 6 1 2 3 2 3 3 3 4 1 1 3 5 2 4 5 1 4 4 2 3
예제 출력 1
7
풀이
그래프 + 최단거리는 우선 BFS이다. 그중에서도 특별한 케이스의 알고리즘이 존재하는데
한 점에서 어딘가로의 최단거리는 다익스트라를 사용하는편이다.
(1 > v1) + (v1 > v2) + (v2 > N)의 합과
(1 > v2) + (v2 > v1) + (v1 > N)의 합 중 최솟값을 출력하였다.
전체 코드
import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.PriorityQueue; import java.util.StringTokenizer; public class BJ_G4_1504_특정한최단경로 { static class Node implements Comparable<Node>{ int end; int cost; Node(int end, int cost) { this.end = end; this.cost = cost; } @Override public int compareTo(Node o) { return this.cost - o.cost; } } static ArrayList<Node>[] list; static int N, E; static final int INF = 200000000; public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); int[] dist1, distV1, distV2; N = Integer.parseInt(st.nextToken()); E = Integer.parseInt(st.nextToken()); list = new ArrayList[N+1]; dist1 = new int[N+1]; distV1 = new int[N+1]; distV2 = new int[N+1]; for(int i=1; i<=N; i++) { list[i] = new ArrayList<>(); dist1[i] = INF; distV1[i] = INF; distV2[i] = INF; } 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()); list[a].add(new Node(b, c)); list[b].add(new Node(a, c)); } st = new StringTokenizer(br.readLine()); int v1 = Integer.parseInt(st.nextToken()); int v2 = Integer.parseInt(st.nextToken()); dijkstra(1, dist1); dijkstra(v1, distV1); dijkstra(v2, distV2); // 1 > v1 > v2 > N int sum1 = dist1[v1] + distV1[v2] + distV2[N]; // 1 > v2 > v1 > N int sum2 = dist1[v2] + distV2[v1] + distV1[N]; int ans = Math.min(sum1, sum2); if(ans >= INF) { System.out.println(-1); } else { System.out.println(ans); } } private static void dijkstra(int start, int[] dist) { PriorityQueue<Node> pq = new PriorityQueue<>(); pq.add(new Node(start, 0)); dist[start] = 0; while(!pq.isEmpty()) { Node now = pq.poll(); if(now.cost > dist[now.end]) { continue; } int len = list[now.end].size(); for(int i=0; i<len; i++) { Node next = list[now.end].get(i); if(dist[next.end] <= now.cost + next.cost) continue; dist[next.end] = now.cost + next.cost; pq.add(new Node(next.end, now.cost+next.cost)); } } } }
728x90'Algorithm > 백준' 카테고리의 다른 글
[백준]15683: 감시(java) (0) 2022.04.28 [백준]12919: A와 B 2(java) (0) 2022.04.27 [백준]16932: 모양 만들기(java) (0) 2022.04.25 [백준]1765: 닭싸움 팀 정하기(java) (1) 2022.04.23 [백준]13023: ABCDE(java) (0) 2022.04.22