After some thought, I came up with:
for (int k = 0; k < N; ++k)
for (int i = 0; i < N; ++i)
for (int j = 0; j <= i; ++j)
dist[j][i] = dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
Now, of course, we need to show it correctly and faster.
Correctness is more difficult to prove, since it is based on the Floyd-Warsall proof, which is nontrivial. Here's a pretty good proof: Floyd-Warsall proof
symmetric. -, , 2 . , , .
dist[i][j][k] i j, {0, ..., k} i j.
dist[i][j][k-1] i j. , .
, :
dist[i][j][k] = min(dist[i][j][k-1], dist[i][k][k-1] + dist[k][j][k-1])
dist[i][k][k] ( dist[k][i][k]):
dist[i][k][k] = min(dist[i][k][k-1], dist[i][k][k-1] + dist[k][k][k-1])
, dist[k][k][k-1] ( ), , dist[i][k][k] = dist[i][k][k-1]. dist[k][k][k-1] = 0, , min().
, dist[i][k][k] = dist[i][k][k-1] dist[i][j][k] , dist[i][k] dist[k][j] k . dist[i][j][k-1] dist[i][j][k], dist[i][j] dist[i][j][k-1] , dist[i][j][k]. i j k, .
, .
, dist[i][j] = dist[j][i] .
, dist[a][b] = dist[b][a] a b.
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])
= min(dist[j][i], dist[k][i] + dist[j][k])
= min(dist[j][i], dist[j][k] + dist[k][i])
= dist[j][i]
, dist[a][b] = dist[b][a]. dist[i][j] = dist[j][i]
, .
. , , . , , , min() - , .
- , , , .
EDIT:
, :
for (int k = 0; k < N; ++k) {
for (int i = 0; i < k; ++i)
for (int j = 0; j <= i; ++j)
dist[i][j] = min(dist[i][j], dist[i][k] + dist[j][k]);
for (int i = k; i < N; ++i) {
for (int j = 0; j < k; ++j)
dist[i][j] = min(dist[i][j], dist[k][i] + dist[j][k]);
for (int j = k; j <= i; ++j)
dist[i][j] = min(dist[i][j], dist[k][i] + dist[k][j]);
}
}
, - , , , .
.