蓝桥杯第1121题——蓝桥公园

题目描述

小明喜欢观景,于是今天他来到了蓝桥公园。

已知公园有 N 个景点,景点和景点之间一共有 M 条道路。小明有 Q 个观景计划,每个计划包含一个起点 st 和一个终点 ed,表示他想从 st 去到 ed。但是小明的体力有限,对于每个计划他想走最少的路完成,你可以帮帮他吗?

输入描述

输入第一行包含三个正整数 N,M,Q

第 2 到 M+1 行每行包含三个正整数 u,v,w,表示 u↔v 之间存在一条距离为 w 的路。

第 M+2 到 M+Q−1 行每行包含两个正整数 st,ed,其含义如题所述。

1 ≤ N ≤ 400,1 ≤ M ≤ 2N×(N−1)​,Q ≤ 10^3,1 ≤ u,v,st,ed ≤ n,1 ≤ w ≤ 10^9

输出描述

输出共 Q 行,对应输入数据中的查询。

若无法从 st 到达 ed 则输出 −1。

输入输出样例

示例 1

输入

复制代码
3 3 3
1 2 1
1 3 5
2 3 2
1 2
1 3
2 3

输出

复制代码
1
3
2

题解思路

这是一道典型的floyd算法模版题,floyd算法相当暴力,时间复杂度O(n^3),适用于像这种只有小几百个点的情况,这种数据量我们不需要考虑其他算法,并且它可以一次计算出所有点到所有点的最短距离 ,对于多次查询的时间复杂度是O(1)。

如果要输出路径,则需要定义一个path数组,需要注意初始化的时候path[i][i] = i表示节点自己到自己的前置节点就是它自己,每连接一条边,都要将path数组做对应更新,最后使用dfs输出路径。

类似图的最短路径算法稳妥的做法是定义每个点自己到自己的最短路径是0,即dp[i][i] = 0,并且不要忘记让每个点到其他点的初始距离定义为极大值INF,建议值是MAX_VALUE的一半。

本题需要考虑点与点之间多重边的情况,我们只保留最短的边信息即可,对于类似题目建议读者都考虑多重边的情况,并且对于每条边是有向边还是无向边要特别注意。

java 复制代码
import java.util.*;
import java.io.*;

public class Main{
    static int n, m, q;
    static long[][] dp;
    static int[][] path;
    static long INF = Long.MAX_VALUE >> 1;
    public static void main(String[] args) throws Exception{
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
        String[] temp = in.readLine().split(" ");
        n = Integer.parseInt(temp[0]);
        m = Integer.parseInt(temp[1]);
        q = Integer.parseInt(temp[2]);
        init();
        for (int i = 0; i < m; i++) {
            temp = in.readLine().split(" ");
            int u = Integer.parseInt(temp[0]);
            int v = Integer.parseInt(temp[1]);
            long w = Long.parseLong(temp[2]);
            // 对于两点之间的边,只保留最短边
            if (w < dp[u][v]) {
                dp[u][v] = dp[v][u] = w;
                // path数组必须同时初始化
                path[u][v] = u;
                path[v][u] = v;
            }
        }
        floyd();
        for (int i = 0; i < q; i++) {
            temp = in.readLine().split(" ");
            int u = Integer.parseInt(temp[0]);
            int v = Integer.parseInt(temp[1]);
            if (dp[u][v] == INF) {
                out.print(-1);
            } else {
                out.print(dp[u][v]);
                // 如有需要,打印路径
                // displayPath(u, v);
                System.out.println();
            }
            out.print("\n");
        }
        out.flush();
    }
    // dfs打印最短路径
    public static void displayPath(int u, int v) {
        // 处理u到v没有路径的情况
        if (path[u][v] == 0) {
            System.out.println(-1);
            return;
        }
        // 有路径情况下的操作
        if (u == v) {
            System.out.print(u + " ");
        } else {
            displayPath(u, path[u][v]);
            System.out.print(v + " ");
        }
    }
    public static void floyd() {
        for (int k = 1; k <= n; k++) {
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= n; j++) {
                    if (dp[i][j] > dp[i][k] + dp[k][j]) {
                        dp[i][j] = dp[i][k] + dp[k][j];
                        // 在i到j的最短路径中,j的前置节点修改为i到k的最短路径的前置节点
                        path[i][j] = path[i][k];
                    }
                }
            }
        }
    }
    public static void init() {
        dp = new long[n + 1][n + 1];
        for (long[] arr : dp) {
            Arrays.fill(arr, INF);
        }
        for (int i = 0; i <= n; i++) {
            dp[i][i] = 0;
        }
        // path数组的初始化
        path = new int[n + 1][n + 1];
        for (int i = 1; i <= n; i++) {
            path[i][i] = i;
        }
    }
}
相关推荐
2401_8318249635 分钟前
基于C++的区块链实现
开发语言·c++·算法
We་ct42 分钟前
LeetCode 918. 环形子数组的最大和:两种解法详解
前端·数据结构·算法·leetcode·typescript·动态规划·取反
愣头不青1 小时前
238.除了自身以外数组的乘积
数据结构·算法
人工智能AI酱1 小时前
【AI深究】逻辑回归(Logistic Regression)全网最详细全流程详解与案例(附大量Python代码演示)| 数学原理、案例流程、代码演示及结果解读 | 决策边界、正则化、优缺点及工程建议
人工智能·python·算法·机器学习·ai·逻辑回归·正则化
WangLanguager1 小时前
逻辑回归(Logistic Regression)的详细介绍及Python代码示例
python·算法·逻辑回归
m0_518019481 小时前
C++与机器学习框架
开发语言·c++·算法
一段佳话^cyx1 小时前
详解逻辑回归(Logistic Regression):原理、推导、实现与实战
大数据·算法·机器学习·逻辑回归
qq_417695051 小时前
C++中的代理模式高级应用
开发语言·c++·算法
xiaoye-duck2 小时前
《算法题讲解指南:动态规划算法--路径问题》--5.不同路径,6.不同路径II
c++·算法·动态规划
ambition202422 小时前
最大子数组和算法全解析:从暴力枚举到动态规划优化
数据结构·c++·算法