๋ชจ๋ ์ ์ต๋จ ๊ฒฝ๋ก ์๊ณ ๋ฆฌ์ฆ - ํ๋ก์ด๋ ์์ (Floyd-Warshall) ์๊ณ ๋ฆฌ์ฆ
- ๊ทธ๋ํ์ ๋ชจ๋ ์ ์ ์์ ๋ค๋ฅธ ์ ์ ์ผ๋ก์ ์ต๋จ ๊ฒฝ๋ก๋ฅผ ๊ตฌํ๋ ๋ฌธ์
- ๊ฐ์ค์น(์์ ๊ฐ์ค์น, ์์ ๊ฐ์ค์น)๊ฐ ํฌํจ๋์ด ์์ผ๋ฉฐ, ๋ฐฉํฅ์ด ์๋ ๊ทธ๋ํ์์ ์ต๋จ ๊ฒฝ๋ก ์ฐพ๊ธฐ
- ๋ชจ๋ ์ ์ ์ ๋ํด ๋ค์ต์คํธ๋ผ ์๊ณ ๋ฆฌ์ฆ์ ์ ์ฉํ์ฌ ํ ์๋ ์์ง๋ง, ํ๋ก์ด๋ ์์ฌ ์๊ณ ๋ฆฌ์ฆ์ DP๋ฅผ ์ด์ฉํ์ฌ ๋ฌธ์ ๋ฅผ ๋์ฑ ์ฝ๊ณ ํจ์จ์ ์ด๊ฒ ํด๊ฒฐํ๋ค.
ํ๋ก์ด๋ ์์ (Floyd-Warshall) ์๊ณ ๋ฆฌ์ฆ
์ ์ i
์์์ ์ j
๊น์ง์ ์ต๋จ ๊ฒฝ๋ก๋ i์์ j๋ก์ ์ง์ ๋น์ฉ๊ณผ, i์ j๊ฐ ์๋ ๋ค๋ฅธ ์ ์ ์ ๊ฑฐ์น๋ ๊ฐ์ ๋น์ฉ์ ๋น๊ตํ์ฌ ๋น์ฉ์ด ๋ ์ ์ ๊ฐ์ด ๋๋ค.- ์ด๋, ๋ชจ๋ ์ ์ต๋จ ๊ฒฝ๋ก๋ฅผ ๊ตฌํ๊ธฐ ์ํด์๋ ๊ฒฝ์ ์ง์ธ
์ ์ k
๋ก์ ์ i
์์์ ์ j
๊น์ง ๋ชจ๋ ์ ์ ์ ๋์ ํด๋ณด์์ผ ํ๋ค. - ๋ฐ๋ผ์
์ ์ i
์์์ ์ j
๊น์ง์ ์ต๋จ ๊ฒฝ๋ก๋ฅผ ๊ตฌํ๋ ๋ฌธ์ ๋ ๋ชจ๋ ์ ์ ์ ๊ฒฝ์ ์ง๋ก ๊ฐ๋ ๋ถ๋ถ๋ฌธ์ ๋ค๋ก ๋๋ ์ ์๋ค. - O(N^3)์ ์๊ฐ๋ณต์ก๋๋ก ๋ฌธ์ ๋ฅผ ํด๊ฒฐ
๋ก์ง
๋ก์ง ๐ก
Di(k)j
= ์ ์ {1, 2, โฆ, k}๋ง์ ๊ฒฝ์ ๊ฐ๋ฅํ ์ ์ ๋ค๋ก ๊ณ ๋ คํ๋,์ ์ i
์์์ ์ j
๊น์ง์ ๋ชจ๋ ๊ฒฝ๋ก ์ค ๊ฐ์ฅ ์งง์ ๊ฒฝ๋ก์ ๊ฑฐ๋ฆฌDi(1)j
๋์ ์ i
์์์ ์ 1
์ ๊ฒฝ์ ํ์ฌ์ ์ j
๊น์ง ๊ฐ๋ ๊ฒฝ๋ก์,์ ์ i
์์์ ์ j
๋ก ์ง์ ๊ฐ๋ฅ ๊ฒฝ๋ก ์ค ์งง์ ๊ฑฐ๋ฆฌ- ๋ง์ฐฌ๊ฐ์ง๋ก
Di(2)j
๋์ ์ i
์์์ ์ 2
์ ๊ฒฝ์ ํ์ฌ์ ์ j
๊น์ง ๊ฐ๋ ๊ฒฝ๋ก์,Di(1)j
์ค ์งง์ ๊ฑฐ๋ฆฌ. ์ด๋, ๊ฒฝ์ ๊ฒฝ๋ก๋Di(1)2 + D2(1)j
๊ฐ ๋๋ฉด์ ๋ถ๋ถ ๋ฌธ์ ๋ฅผ ๊ฐ๊ฒ ๋จ.- ๊ฒฐ๊ตญ
Dikj
๋์ ์ i
์์์ ์ k
๋ฅผ ๊ฒฝ์ ํ์ฌ์ ์ j
๊น์ง ๊ฐ๋ ๊ฒฝ๋ก์,Di(k-1)j
์ค ์งง์ ๊ฑฐ๋ฆฌ. ์ด๋, ๊ฒฝ์ ๊ฒฝ๋ก๋Di(k-1)k + Dk(k-1)j
๊ฐ ๋๋ฉด์ ๋ถ๋ถ ๋ฌธ์ ๋ฅผ ๊ฐ๊ฒ ๋จ.
๊ตฌํ
Java
public class FloydWarshallTest {
static final int INF = 99999; // ๋๋ฌํ ์ ์๋ ๊ฒฝ๋ก์ ๊ฐ์ค์น(์ค๋ฒํ๋ก์ฐ๊ฐ ๋ฐ์ํ์ง ์๋๋ก Integer.MAX_VALUE ์ค์ ํ์ง ์์)
static int N;
static int[][] dp;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
dp = new int[N][N];
// ๊ฒฝ๋ก ๋น์ฉ ์ด๊ธฐํ
for (int i=0; i<N; i++) {
for (int j=0; j<N; j++) {
dp[i][j] = sc.nextInt();
if (i != j && dp[i][j] == 0) dp[i][j] = INF; // ๋๋ฌํ ์ ์๋ ๊ฒฝ๋ก๋ ๋น์ฉ์ ์ต๋๋ก ์ด๊ธฐํ
}
}
positiveFloydWarshall(); // ์์ ๊ฐ์ค์น ์ต๋จ ๊ฒฝ๋ก
negativeFloydWarshall(); // ์์ ๊ฐ์ค์น ์ต๋จ ๊ฒฝ๋ก
}
// ์์ ๊ฐ์ค์น ์ต๋จ ๊ฒฝ๋ก
public static void positiveFloydWarshall() {
for (int k=0; k<N; k++) {
for (int i=0; i<N; i++) {
if (i == k) continue; // ๊ฒฝ์ ์ง = ์ถ๋ฐ์ง์ธ ๊ฒฝ์ฐ pass
for (int j=0; j<N; j++) {
// if (i == j || i == j) continue; // ๊ฒฝ์ ์ง = ๋์ฐฉ์ง์ธ ๊ฒฝ์ฐ, ์ถ๋ฐ์ง = ๋์ฐฉ์ง์ธ ๊ฒฝ์ฐ pass. ํ์ง๋ง ์ด์ฐจํผ ์๊ธฐ์์ ์ผ๋ก์ ์ด๋์ ๋น์ฉ์ด 0์ด๋ฏ๋ก ์๋ต ๊ฐ๋ฅ
dp[i][j] = Math.min(dp[i][j], dp[i][k] + dp[k][j]);
}
}
}
}
// ์์ ๊ฐ์ค์น ์ต๋จ ๊ฒฝ๋ก
public static void negativeFloydWarshall() {
for (int k=0; k<N; k++) {
for (int i=0; i<N; i++) {
if (i == k) continue; // ๊ฒฝ์ ์ง = ์ถ๋ฐ์ง์ธ ๊ฒฝ์ฐ pass
for (int j=0; j<N; j++) {
if (i == j) continue; // ์ถ๋ฐ์ง = ๋์ฐฉ์ง์ธ ๊ฒฝ์ฐ
if (dp[i][k] != INF && dp[k][j] != INF) // ์์ ๊ฐ์ค์น๋ ๋๋ฌํ ์ ์๋ ๊ฒฝ๋ก์ ๋น์ฉ๋ ๊ฐ์์์ผ ๋๋ฌํ ์ ์๋ ๊ฒ์ฒ๋ผ ๋ง๋ค ์ ์์ผ๋ฏ๋ก ์ ์ด์ ๋๋ฌํ ์ ์๋ ๊ณณ์ pass
dp[i][j] = Math.min(dp[i][j], dp[i][k] + dp[k][j]);
}
}
}
}
}