洛谷P2910 [USACO08OPEN]Clear And Present Danger S 题解 Floyd求最短路

题目链接:https://www.luogu.com.cn/problem/P2910

Floyd—Warshall算法的原理是动态规划。

\(dis[i][j][k]\) 为从 \(i\)\(j\) 只以 \(1 \sim k\) 中节点为中间结点的最短路径长度,则:

(1)若最短路径经过点 \(k\) ,那么 \(dis[i][j][k]=dis[i][k][k-1]+dis[k][j][k-1]\)

(2)若最短路径不经过点 \(k\) ,那么 \(dis[i][j][k]=dis[i][j][k-1]\)

因此 \(dis[i][j][k]=min(dis[i][k][k-1]+dis[k][j][k-1], dis[i][j][k-1])\)

如果我们把 \(k\) 放在最外层的循环,那么第三位在实现上可以省去。

实现代码如下:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 110, maxm = 10010;
int n, m, g[maxn][maxn], road[maxm], dist[maxn][maxn], ans;
const int INF = (1<<29);
int main() {
    cin >> n >> m;
    for (int i = 1; i <= m; i ++) cin >> road[i];
    for (int i = 1; i <= n; i ++) {
        for (int j = 1; j <= n; j ++) {
            cin >> g[i][j];
            dist[i][j] = (i == j) ? 0 : g[i][j];
        }
    }
    for (int k = 1; k <= n; k ++)
        for (int i = 1; i <= n; i ++)
            for (int j = 1; j <= n; j ++)
                dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
    for (int i = 1; i < m; i ++)
        ans += dist[ road[i] ][ road[i+1] ];
    cout << ans << endl;
    return 0;
}
posted @ 2020-05-22 00:39  quanjun  阅读(191)  评论(0编辑  收藏  举报