https://www.acmicpc.net/problem/7040

4 2 1
1 3 10
2 4 20
2 3 3


위의 과정을 벨만-포드를 적용하여 이해해보자
에지리스트 – (c1, c2, d)순
(1, 3, 10)
(2, 4, 20)
(2, 3, 3)
1번째 업데이트
(1)(1, 3, 10)
(2) (2, 4, 20)
(3) (2, 3, 3)은 최소 거리이고 우리는 3번 소의 distance[3] = 10 (!= ∞)
라는 것을 이용해서 distance[2] = distance[3] – 10 = 7로 업데이트
여기서
MD배열에서 distance[c2] != ∞이면 distance[c1] = distance[c2] – d로 계산할 수 있다.
ML배열은 일반적인 벨만포드와 같이 계산하면 된다.
2번째 업데이트
(1)(1, 3, 10)
(2) (2, 4, 20)
(3) (2, 3, 3)
최종적으로 한번 더 에지리스트를 순회하여
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
static int[] distance; // 거리 배열
static List<Edge> edge = new ArrayList<>(); // 에지 리스트
static int N;
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());
int ML = Integer.parseInt(st.nextToken());
int MD = Integer.parseInt(st.nextToken());
distance = new int[N+1];
Arrays.fill(distance, Integer.MAX_VALUE);
// ML 입력받기
for (int i = 0; i < ML; i++) {
st = new StringTokenizer(br.readLine());
int c1 = Integer.parseInt(st.nextToken());
int c2 = Integer.parseInt(st.nextToken());
int d = Integer.parseInt(st.nextToken());
edge.add(new Edge("ML", c1, c2, d));
}
// MD 입력받기
for (int i = 0; i < MD; i++) {
st = new StringTokenizer(br.readLine());
int c1 = Integer.parseInt(st.nextToken());
int c2 = Integer.parseInt(st.nextToken());
int d = Integer.parseInt(st.nextToken());
edge.add(new Edge("MD", c1, c2, d));
}
// 시작 노드의 거리 배열 값은 0이다.
distance[1] = 0;
// N-1번 벨만-포드를 반복한다.
for (int i = 0; i < N - 1; i++) {
for (Edge e : edge) {
if(e.mode.equals("ML")) {
if(distance[e.c1] != Integer.MAX_VALUE && distance[e.c2] > distance[e.c1] + e.d) {
distance[e.c2] = distance[e.c1] + e.d;
}
} else if(e.mode.equals("MD")) {
if(distance[e.c2] != Integer.MAX_VALUE && distance[e.c1] > distance[e.c2] - e.d) {
distance[e.c1] = distance[e.c2] - e.d;
}
}
}
}
boolean imPossible = false;
for (Edge e : edge) {
if(e.mode.equals("ML")) {
if(distance[e.c1] != Integer.MAX_VALUE && distance[e.c2] > distance[e.c1] + e.d) {
imPossible = true;
}
} else if(e.mode.equals("MD")) {
if(distance[e.c2] != Integer.MAX_VALUE && distance[e.c1] > distance[e.c2] - e.d) {
imPossible = true;
}
}
}
if(imPossible) System.out.println(-1);
else if(distance[N] == Integer.MAX_VALUE) System.out.println(-2);
else System.out.println(distance[N]);
}
static class Edge {
String mode;
int c1;
int c2;
int d;
Edge(String mode, int c1, int c2, int d) {
this.mode = mode;
this.c1 = c1;
this.c2 = c2;
this.d = d;
}
}
}
백준 7040번은 "최대 거리"를 직접 구하는 문제가 아닙니다.
실제로는 제약조건을 만족하는 최소 거리를 구하는 문제예요.
c2 - c1 ≤ d 즉, c2는 c1보다 최대 d만큼 멀다. 👉 최단거리 그래프의 "정방향 간선" 제약처럼 동작.c2 - c1 ≥ d 즉, c1은 c2보다 최소 d만큼 가깝다. 👉 c1 ≤ c2 - d라는 불평등식. 이 역시 "최단거리 제약" 형태.즉, 이 문제는
“모든 ML/MD 조건을 만족하는 가장 작은 거리들”을 찾아야 함 = 최단경로 문제.