1 条题解

  • 0
    @ 2026-10-27 12:58:42

    思路与算法

    对每条无向边,用两点坐标差的平方和开平方计算长度。距离矩阵对角为0、无边为无穷,随后运行Floyd:依次允许每个点作为中间点,d[i][j]=min(d[i][j],d[i][k]+d[k][j])。最后输出s到t距离,不能到达时输出-1.00。

    正确性说明

    初始化矩阵恰表示不经过中间点的路径。处理第k个中间点时,最短路径要么不经过k,要么可拆为i到k与k到j两段;两段的其他中间点都已被允许。由k归纳,完成后覆盖所有可能路径。边长非负,零长度连线与同点起终点也正确。

    复杂度

    初始化O(n²),读边O(m),Floyd O(n³);总时间O(n³+m),空间O(n²)。用long double保存距离,以两位输出并按声明容差判定。

    易错点

    无向边须同时赋值两个方向。同坐标不代表没有边,长度可为0;不能用0来表示本题距离矩阵的无边。无路输出-1.00,数值必须有限并保留两位。

    参考代码(C++11)

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        int n;
        cin >> n;
        vector<int> x(n), y(n);
        for (int i = 0; i < n; ++i)
            cin >> x[i] >> y[i];
        vector<vector<long double>> d(n, vector<long double>(n, 1e30L));
        for (int i = 0; i < n; ++i)
            d[i][i] = 0;
        int m;
        cin >> m;
        while (m--) {
            int u, v;
            cin >> u >> v;
            --u;
            --v;
            long double a = x[u] - x[v], b = y[u] - y[v];
            d[u][v] = d[v][u] = sqrtl(a * a + b * b);
        }
        int s, t;
        cin >> s >> t;
        --s;
        --t;
        for (int k = 0; k < n; ++k)
            for (int i = 0; i < n; ++i)
                for (int j = 0; j < n; ++j)
                    d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
        if (d[s][t] > 1e29L)
            cout << "-1.00\n";
        else
            cout << fixed << setprecision(2) << d[s][t] << "\n";
    }
    
    • 1

    信息

    ID
    2066
    时间
    1000ms
    内存
    64MiB
    难度
    普及
    标签
    递交数
    0
    已通过
    0
    上传者