https://www.acmicpc.net/problem/11404
정답률 41.877%
n(2 ≤ n ≤ 100)개의 도시가 있다. 그리고 한 도시에서 출발하여 다른 도시에 도착하는 m(1 ≤ m ≤ 100,000)개의 버스가 있다. 각 버스는 한 번 사용할 때 필요한 비용이 있다.
모든 도시의 쌍 (A, B)에 대해서 도시 A에서 B로 가는데 필요한 비용의 최솟값을 구하는 프로그램을 작성하시오.
5
14
1 2 2
1 3 3
1 4 1
1 5 10
2 4 2
3 4 1
3 5 1
4 5 3
3 5 10
3 1 8
1 4 2
5 1 7
3 4 2
5 2 4
0 2 3 1 4
12 0 15 2 5
8 5 0 1 1
10 7 13 0 3
7 4 10 6 0
모든 노드끼리의 최소 경로를 구해야 한다. 이는 플로이드-워셜 알고리즘으로 해결할 수 있다. 도시의 최대 개수가 으로 시간복잡도로 가능하다.
플로이드-워셜은 인접 행렬을 이용하여 그래프를 나타낸다. 자기 자신과의 거리는 0으로 저장하고 나머지는 충분히 큰 값으로 초기화한 뒤 갱신해나간다.
dist = new int[N + 1][N + 1];
for (int i = 0; i < N + 1; i++) {
Arrays.fill(dist[i], INF);
for (int j = 0; j < N + 1; j++) {
//자기 자신과의 거리는 0
if (i == j) {
dist[i][j] = 0;
}
}
}
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
int start = Integer.parseInt(st.nextToken()); //시작 도시
int end = Integer.parseInt(st.nextToken()); //도착 도시
int cost = Integer.parseInt(st.nextToken()); //비용
if (dist[start][end] > cost) {
dist[start][end] = cost;
}
}
그리고 플로이드-워셜 알고리즘을 수행하는데 다음 점화식을 3중 for문으로 모든 중간 경로를 탐색한다.
static void floydWarshall() {
//모든 경유지에 대해 탐색
for (int via = 1; via <= N; via++) {
for (int start = 1; start <= N; start++) {
for (int end = 1; end <= N; end++) {
int newDist = dist[start][via] + dist[via][end];
dist[start][end] = Math.min(dist[start][end], newDist);
}
}
}
}
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
//백준
public class Main {
static final int INF = 100_000_001; //충분히 큰 값
static int[][] dist;
static int N;
public static void main(String[] args) throws IOException {
System.setIn(new FileInputStream("src/input.txt"));
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
N = Integer.parseInt(br.readLine()); //도시의 개수
int M = Integer.parseInt(br.readLine()); //버스의 개수
//인접 행렬 초기화
dist = new int[N + 1][N + 1];
for (int i = 0; i < N + 1; i++) {
Arrays.fill(dist[i], INF);
for (int j = 0; j < N + 1; j++) {
//자기 자신과의 거리는 0
if (i == j) {
dist[i][j] = 0;
}
}
}
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
int start = Integer.parseInt(st.nextToken()); //시작 도시
int end = Integer.parseInt(st.nextToken()); //도착 도시
int cost = Integer.parseInt(st.nextToken()); //비용
if (dist[start][end] > cost) {
dist[start][end] = cost;
}
}
floydWarshall();
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
if (dist[i][j] == INF) {
sb.append(0).append(" ");
} else {
sb.append(dist[i][j]).append(" ");
}
}
sb.append("\n");
}
System.out.println(sb);
}
static void floydWarshall() {
//모든 경유지에 대해 탐색
for (int via = 1; via <= N; via++) {
for (int start = 1; start <= N; start++) {
for (int end = 1; end <= N; end++) {
int newDist = dist[start][via] + dist[via][end];
dist[start][end] = Math.min(dist[start][end], newDist);
}
}
}
}
}