봄봄.devlog
백준 1504번 :: 특정한 최단경로 본문
1504번: 특정한 최단 경로
첫째 줄에 정점의 개수 N과 간선의 개수 E가 주어진다. (2 ≤ N ≤ 800, 0 ≤ E ≤ 200,000) 둘째 줄부터 E개의 줄에 걸쳐서 세 개의 정수 a, b, c가 주어지는데, a번 정점에서 b번 정점까지 양방향 길이 존
www.acmicpc.net
✍ 문제 풀이
- 문제에서 정점은 물론 간선도 여러 번 이동할 수 있다고 하였다.
- 단, 특정 정점 2개를 반드시 거쳐야 한다고 명시하였다.
- 어떻게 생각하면 될까?
- 원래 거쳐야 하는 정점이 없다면, 1부터 N까지 다익스트라 1번만 실행하면 된다.
- But, 거쳐야 하는 정점이 있다면 쪼개서 다익스트라를 하면 된다.
- 1 -> v1 -> v2 -> N
- 1 -> v2 -> v1 -> N
- 1에서v1 / v1에서 v2 / v2에서 N까지로 다익스트라 3번 수행
- 나중에 합산해서 최단 경로를 구하면 된다.
- 다만, N까지 도달하지 못할 경우 -1을 출력
- 이때, INF를 설정하는데 있어서 주의해야 한다. Integer.MAX_VALUE를 설정하면 오버플로우 발생!
- INF = 200,000(간선의 최대 갯수) * 1,000(가중치 최댓값) = 200,000,000
✍ 소스 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
public class Q1504_특정한최단경로 {
static int n, e;
static ArrayList<ArrayList<Node>> list;
static int vertex1, vertex2;
static int[] dist; // 시작점에서 정점으로 가는 최단거리
static boolean[] visited;
static final int INF = 200000000;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken()); // 정점의 개수
e = Integer.parseInt(st.nextToken()); // 간선의 개수
list = new ArrayList<>();
dist = new int[n+1];
visited = new boolean[n + 1];
Arrays.fill(dist, INF);
for(int i=0; i<=n; i++) {
list.add(new ArrayList<>());
}
for(int i=0; i<e; i++) {
st = new StringTokenizer(br.readLine());
int v1 = Integer.parseInt(st.nextToken());
int v2 = Integer.parseInt(st.nextToken());
int w = Integer.parseInt(st.nextToken());
list.get(v1).add(new Node(v2, w));
list.get(v2).add(new Node(v1,w));
}
st = new StringTokenizer(br.readLine());
vertex1 = Integer.parseInt(st.nextToken());
vertex2 = Integer.parseInt(st.nextToken());
// 1 -> v1 -> v2 -> N
int ans1 = 0;
ans1 += dijkstra(1,vertex1);
ans1 += dijkstra(vertex1,vertex2);
ans1 += dijkstra(vertex2,n);
// 1 -> v2 -> v1 -> N
int ans2 = 0;
ans2 += dijkstra(1,vertex2);
ans2 += dijkstra(vertex2,vertex1);
ans2 += dijkstra(vertex1,n);
int result = (ans1 >= INF && ans2 >= INF) ? -1 : Math.min(ans1,ans2);
System.out.println(result);
}
static class Node implements Comparable<Node> {
int v;
int weight;
public Node(int v, int weight) {
this.v = v;
this.weight = weight;
}
@Override
public int compareTo(Node node) {
return this.weight - node.weight;
}
}
static int dijkstra(int v1, int v2) {
Arrays.fill(dist, INF);
Arrays.fill(visited, false);
PriorityQueue<Node> pq = new PriorityQueue<>();
boolean[] visited = new boolean[n+1];
pq.add(new Node(v1, 0));
dist[v1] = 0;
while(!pq.isEmpty()) {
int current = pq.poll().v;
visited[current] = true;
for(Node node : list.get(current)) {
if(visited[node.v]) continue;
if(dist[current]+node.weight >= dist[node.v]) continue;
dist[node.v] = dist[current]+node.weight;
pq.add(new Node(node.v, dist[node.v]));
}
}
return dist[v2];
}
}
'Algorithm > 백준' 카테고리의 다른 글
백준 1655번 :: 가운데로 말해요 (0) | 2020.11.05 |
---|---|
백준 2293번 :: 동전 1 (DP) (0) | 2020.10.09 |
백준 4963번 :: 섬의 개수(DFS) (0) | 2020.08.28 |
백준 2667번 :: 단지 번호 붙이기 (DFS) Java (0) | 2020.08.28 |
백준 7576번 :: 토마토 (BFS) (0) | 2020.08.23 |
Comments