728x90
반응형
1504 - 특정한 최단 경로
https://www.acmicpc.net/problem/1504

문제
방향성 X 그래프/ 1 ~ N번 정점으로 최단 거리 이동 (임의로 주어진 두 정점 반드시 통과)
한번 이동했던 정점, 간선 다시 이동 O
입력
첫째 줄: 정점의 개수 N (2 <= N <= 800), 간선의 개수 E (0 <= E <= 200,00)
둘째 줄 ~ E개의 줄: a, b, c (1 <= c <= 1,000) (a번 정점에서 b번 정점까지 양방향 길 존재, 거리 c)
다음 줄: 반드시 거쳐야 하는 두 개의 서로 다른 정점 번호 v1, v2 (v1 != v2, v1 != N, v2 != N)
(임의의 두 정점 u, v 사이에 간선 최대 1개 존재)
출력: 두 개의 정점 지나는 최단 경로 길이 / 없으면 -1
풀이
Dijkstra(다익스트라) 알고리즘
- 한 정점으로부터 다른 모든 정점까지의 최단 거리(최소 비용)
- 가장 가까운 노드부터 탐색하면서 주변 노드의 거리 하나씩 갱신
- 현재까지 방문한 노드 중 최단 거리가 확정된 노드 기준으로 인접한 노드의 최단 거리 후보값 갱신 반복
- 가중치가 음수가 아닌 그래프에서 사용
- `dist[i]`: `start`에서 i번 노드까지의 최단 거리
- `Arrays.fill(dist, INF)`: 큰 수로 초기화 -> 아직 방문 X
- `dist[start] = 0`: 자기 자신까지 거리 0
=> dist = [∞, 0, ∞, ∞, ∞, ∞]
- `PriorityQueue`: 노드 번호, 현재 거리
- 가장 작은 가중치 가진 노드 먼저 나옴 -> 현재까지 가장 가까운 노드부터 탐색
- `cur.weight > dist[cur.to]`: 이미 더 짧은 경로 방문 노드 무시
static int[] dijkstra(int start) {
int[] dist = new int[N + 1];
Arrays.fill(dist, INF);
dist[start] = 0;
PriorityQueue<Node> pQ = new PriorityQueue<>();
pQ.offer(new Node(start, 0));
while (!pQ.isEmpty()) {
Node cur = pQ.poll();
if (cur.weight > dist[cur.to]) continue;
for (Node next : graph.get(cur.to)) {
if (dist[next.to] > dist[cur.to] + next.weight) {
dist[next.to] = dist[cur.to] + next.weight;
pQ.offer(new Node(next.to, dist[next.to]));
}
}
}
return dist;
}
- 다익스트라 3회 실행
- `dist1`: 1번 노드에서 각 노드까지
- `distV1`: v1에서 각 노드까지
- `distV2`: v2에서 각 노드까지
- 두 경로 거리 계산 후 비교
- 1 -> V1 -> V2 -> N
- 1 -> V2 -> V1 -> N
int[] dist1 = dijkstra(1);
int[] distV1 = dijkstra(v1);
int[] distV2 = dijkstra(v2);
long path1 = (long) dist1[v1] + distV1[v2] + distV2[N];
long path2 = (long) dist1[v2] + distV2[v1] + distV1[N];
long ans = Math.min(path1, path2);
코드
import java.io.*;
import java.util.*;
// 특정한 최단 경로
public class boj_1504 {
static int N, E;
static List<List<Node>> graph;
static int INF = 200_000_100;
static class Node implements Comparable<Node> {
int to, weight;
public Node(int to, int weight) {
this.to = to;
this.weight = weight;
}
@Override
public int compareTo(Node o) {
return this.weight - o.weight;
}
}
static int[] dijkstra(int start) {
int[] dist = new int[N + 1];
Arrays.fill(dist, INF);
dist[start] = 0;
PriorityQueue<Node> pQ = new PriorityQueue<>();
pQ.offer(new Node(start, 0));
while (!pQ.isEmpty()) {
Node cur = pQ.poll();
if (cur.weight > dist[cur.to]) continue;
for (Node next : graph.get(cur.to)) {
if (dist[next.to] > dist[cur.to] + next.weight) {
dist[next.to] = dist[cur.to] + next.weight;
pQ.offer(new Node(next.to, dist[next.to]));
}
}
}
return dist;
}
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());
graph = new ArrayList<>();
for (int i = 1; i <= N; i++) {
graph.add(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());
graph.get(a).add(new Node(b, c));
graph.get(b).add(new Node(c, a));
}
st = new StringTokenizer(br.readLine());
int v1 = Integer.parseInt(st.nextToken());
int v2 = Integer.parseInt(st.nextToken());
int[] dist1 = dijkstra(1);
int[] distV1 = dijkstra(v1);
int[] distV2 = dijkstra(v2);
long path1 = (long) dist1[v1] + distV1[v2] + distV2[N];
long path2 = (long) dist1[v2] + distV2[v1] + distV1[N];
long ans = Math.min(path1, path2);
System.out.println(ans >= INF ? -1 : ans);
}
}728x90
반응형
'✏️ > BOJ' 카테고리의 다른 글
| [BOJ/BFS] 백준 1707 - 이분 그래프 (Java) (0) | 2025.11.12 |
|---|---|
| [BOJ/DFS+BFS] 백준 14502 - 연구소 (Java) (0) | 2025.11.12 |
| [BOJ/MST] 백준 1647 - 도시 분할 계획 (Java) (0) | 2025.11.11 |
| [BOJ] 백준 2252 - 줄 세우기 (Java) (0) | 2025.11.11 |
| [BOJ/DFS+DP] 백준 2533 - 사회망 서비스(SNS) (Java) (0) | 2025.11.10 |