Floyd求最短路

93 阅读1分钟

之前一直以为Floyd就是普通的三重循环暴力,今天才懂蕴含着动态规划的思想

题目思路

  1. g[k][i][j]数组含义:从1k的节点作为中间经过的节点时,从ij的最短路径长度。
  2. 状态转移方程 g[k][i][j] = min(g[k-1][i][j] , g[k-1][i][k] + g[k-1][k][j]),表示g[k][i][j]①经过1k-1,不经过k节点;②不经过1k-1,经过k节点。
  3. 根据动态规划g[k]只可能与g[k-1]有关系,所以可以省略最外层的维度k,直接带入循环求解。

C++代码

#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

const int N = 210;

int n, m, k;
int g[N][N];

void Floyd()
{
    for (int k = 1; k <= n; k++)
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
                g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
}

int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);

    cin >> n >> m >> k;

    memset(g, 0x3f, sizeof g);
    for (int i = 1; i <= n; i++)
    {
        g[i][i] = 0;
    }

    while (m--)
    {
        int a, b, w;
        cin >> a >> b >> w;
        g[a][b] = min(g[a][b], w);
    }

    Floyd();

    while (k--)
    {
        int a, b;
        cin >> a >> b;
        if (g[a][b] > 0x3f3f3f3f / 2)
        {
            cout << "impossible" << endl;
        }
        else
        {
            cout << g[a][b] << endl;
        }
    }
    return 0;
}