当前位置: 首页 > news >正文

Floyd 算法 Java

图论算法实践:使用 Floyd 求任意两点最短路(Java 实现)

在图论算法中,Floyd-Warshall 算法是一个经典的动态规划算法,用于在一个加权图中寻找所有点对之间的最短路径


场景描述

假设我们有一个包含 n 个点的无向图,图中有 m 条边,每条边连接两个点并带有一定的权重。我们还需要回答 q 个询问,每个询问是从点 x 到点 y 的最短路径长度。如果两点之间不可达,输出 -1


解决方案:Floyd-Warshall 算法

Floyd-Warshall 是一个三重循环的动态规划算法,时间复杂度为 O(n^3),适用于点数较少的图。

核心思想

我们维护一个 dist[i][j] 数组,表示从点 i 到点 j 的最短路径长度。初始时,dist[i][j] 设为边权(或正无穷),然后不断尝试通过中转点 k 来优化从 ij 的路径。


Java 实现代码

// 包名可自定义
package ff;

import java.io.*;
import java.util.*;

public class Main {
	static FastRead in = new FastRead();
	static PrintWriter out = new PrintWriter(System.out);

	public static void main(String[] args) {
		int n = in.nextInt();  // 点数
		int m = in.nextInt();  // 边数
		int q = in.nextInt();  // 查询数

		long[][] dist = new long[n + 1][n + 1];

		// 初始化邻接矩阵
		for (int i = 1; i <= n; i++) {
			Arrays.fill(dist[i], Long.MAX_VALUE);
			dist[i][i] = 0;  // 自己到自己距离为0
		}

		// 读入边并更新最短路径(无向图)
		while (m-- > 0) {
			int u = in.nextInt();
			int v = in.nextInt();
			long w = in.nextLong();
			dist[u][v] = Math.min(dist[u][v], w);
			dist[v][u] = Math.min(dist[v][u], w);
		}

		// 核心算法:Floyd-Warshall 三重循环
		for (int k = 1; k <= n; k++) {
			for (int i = 1; i <= n; i++) {
				for (int j = 1; j <= n; j++) {
					if (dist[i][k] != Long.MAX_VALUE && dist[k][j] != Long.MAX_VALUE) {
						dist[i][j] = Math.min(dist[i][j], dist[i][k] + dist[k][j]);
					}
				}
			}
		}

		// 处理查询
		while (q-- > 0) {
			int x = in.nextInt();
			int y = in.nextInt();
			out.println(dist[x][y] != Long.MAX_VALUE ? dist[x][y] : -1);
		}
		out.flush();
		out.close();
	}
}

辅助类 FastRead

为了提升输入效率,使用了封装的快速读入类:

class FastRead {
	StringTokenizer st;
	BufferedReader br;

	public FastRead() {
		br = new BufferedReader(new InputStreamReader(System.in));
	}

	String next() {
		while (st == null || !st.hasMoreElements()) {
			try {
				st = new StringTokenizer(br.readLine());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return st.nextToken();
	}

	int nextInt() {
		return Integer.parseInt(next());
	}

	double nextDouble() {
		return Double.parseDouble(next());
	}

	long nextLong() {
		return Long.parseLong(next());
	}

	String nextLine() {
		String str = null;
		try {
			str = br.readLine();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return str;
	}
}

示例输入输出说明

假设输入为:

4 5 3
1 2 3
2 3 4
3 4 5
4 1 2
1 3 10
1 3
2 4
1 4

输出应为:

7
9
2

注意事项

  • 边可能有重边,需取最小值处理。

  • 初始化时要小心:dist[i][j] = Long.MAX_VALUE 会导致溢出问题,必须判断是否为 MAX_VALUE 再加法。

  • 点编号从 1 开始,数组大小应为 n + 1


总结

Floyd-Warshall 是处理稠密图、所有点对路径问题的强力工具,使用简单,效率可接受。


如果你喜欢这样的算法详解,也欢迎点赞、收藏或留言交流!

http://www.dtcms.com/a/112546.html

相关文章:

  • Go/Rust 疯狂蚕食 Java 市场?老牌语言的 AI 化自救之路
  • 自编码器(AutoEncoder)概念解析与用法实例:压缩数字图像
  • 使用人工智能大模型DeepSeek,如何免费辅助教学?
  • 如何实现单例模式?
  • Java常用工具算法-4--签名算法(RSA,ECDSA,HMAC等)
  • 不同路径I
  • 洛谷题单3-P1720 月落乌啼算钱(斐波那契数列)-python-流程图重构
  • 迪杰斯特拉+二分+优先队列+拓扑+堆优化(奶牛航线Cowroute、架设电话线dd、路障Roadblocks、奶牛交通Traffic)
  • Leetcode 437 -- dfs | 前缀和
  • 大数据概念介绍
  • 高可用完全分布式集群启动命令
  • 基于 Java 的异步任务管理器的设计与实现方案
  • Currying柯里化
  • 【教程】Windows下 Xshell 连接跳板机和开发机
  • 基于PI控制和卡尔曼滤波的光通信相位偏差估计和补偿算法matlab仿真
  • 前端快速入门学习1——使用工具
  • [ISP 3A ] AE的常用算法分析
  • chown和chmod的区别
  • 使用内存数据库来为mapper层的接口编写单元测试
  • AI大模型时代前后端技术演进:MCP神经中枢架构下的技术栈抉择
  • Java项目之基于ssm的教务信息平台的设计与实现
  • 算法思想之双指针(一)
  • 深度学习处理文本(11)
  • Prolog语言的移动UI设计
  • COBOL语言的数据库交互
  • Pascal语言的设备管理
  • 【含文档+PPT+源码】基于SpringBoot+vue的疫苗接种系统的设计与实现
  • Scala学习总结③
  • JavaScript事件循环深度解析:从一道面试题看微任务与宏任务调度机制
  • 详细说明Qt 中共享内存方法: QSharedMemory 对象