【图论】「极简复习版」最短路径 Java/C++ 实现

news2024/11/23 1:13:12

文章目录

    • Dijkstra —— 单源最短路
      • 讲解
      • 图解
      • Java
        • 朴素
        • 使用堆优化
      • C++
        • 朴素
        • 使用堆优化
    • Floyd —— 多源最短路
      • 讲解
      • Java
      • C++

Dijkstra —— 单源最短路

讲解

时间复杂度

  • 朴素 Dijkstra: O ( n 2 ) O(n^2) O(n2) n n n 是顶点数。
  • 堆优化 Dijkstra: O ( m   l o g n ) O(m\ logn) O(m logn) m m m 是边数, n n n 是顶点数。

核心思想:具体看图解,文字和图我感觉都挺详细的。

适用场景:

  • 朴素 Dijkstra:稠密图
  • 堆优化 Dijkstra:稀疏图

图解

image-20230112102534494

image-20230114041805643

Java

朴素

static final int MAX = 1000;
static final int INF = 0xffffff; // 无穷大
static int[][] edge = new int[MAX][MAX]; // 邻接矩阵
static int[] dis = new int[MAX]; // 记录从起点到各个点的最短路径
static boolean[] vis = new boolean[MAX]; // 标记
static int n, m, s; // 顶点数、边数

public static void dijkstra(int s) {
    Arrays.fill(dis, INF);
    dis[s] = 0;
    for(int i = 1; i <= n; i++) { // 保证每个顶点都会被访问
        int u = 0;
        // 从未使用过的顶点中选一个距离起点的最短路径
        for(int v = 1; v <= n; v++) {
            if(!vis[v] && dis[u] > dis[v]) u = v;
        }
        vis[u] = true;
        // 更新 u 所有邻接点的路径
        for(int v = 1; v <= n; v++) {
            // 当前结点 u 的距离(起点到 u 的距离) + 结点 u 的邻接点 v < 结点 v 的距离,则更新
            dis[v] = Math.min(dis[v], edge[u][v] + dis[u]);
        }
    }
}

使用堆优化

import java.util.*;

public class Main {
    static final int MAX = 150005;
    static final int INF = 0x7ffffff;
    static ArrayList<Edge>[] G = new ArrayList[MAX];
    static int[] dis = new int[MAX];
    static boolean[] vis = new boolean[MAX];
    static int n, m;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt(); m = sc.nextInt();
        for(int i = 1; i <= n; i++) G[i] = new ArrayList<>();
        while(m-- != 0) {
            int u = sc.nextInt(), v = sc.nextInt(), w = sc.nextInt();
            G[u].add(new Edge(v, w));
        }
        dijkstra(1);
        System.out.println(dis[n] == INF ? -1 : dis[n]);
    }

    public static void dijkstra(int s) {
        PriorityQueue<Edge> queue = new PriorityQueue<>();
        Arrays.fill(dis, INF);
        queue.add(new Edge(s, 0));
        dis[s] = 0;
        while(!queue.isEmpty()) {
            int u = queue.poll().to; // 距离最短的点
            if(vis[u]) continue;
            vis[u] = true;
            for(int i = 0; i < G[u].size(); i++) { // 更新邻接点
                Edge v = G[u].get(i);
                if(dis[v.to] > dis[u] + v.w) {
                    dis[v.to] = dis[u] + v.w;
                    queue.add(new Edge(v.to, dis[v.to]));
                }
            }
        }
    }

}

class Edge implements Comparable<Edge> {
    int to, w;
    public Edge(int to, int w) {
        this.to = to;
        this.w = w;
    }

    @Override
    public int compareTo(Edge o) {
        return this.w - o.w;
    }
}

C++

朴素

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

using namespace std;

const int N = 510;
const int INF = 0x3f3f3f3f;

int G[N][N];
int dist[N];
bool vis[N];

int n, m;

void dijkstra(int s) {
    memset(dist, INF, sizeof(dist));
    dist[s] = 0;
    for(int i = 1; i <= n; i++) {
        int u = 0;
        for(int v = 1; v <= n; v++) {
            if(!vis[v] && dist[u] >  dist[v]) u = v;
        }
        vis[u] = true;
        for(int v = 1; v <= n; v++) {
            dist[v] = min(dist[v], G[u][v] + dist[u]);
        }
    }
}

int main() {
    cin >> n >> m;
    memset(G, INF, sizeof(G));
    while(m--) {
        int u, v, w;
        cin >> u >> v >> w;
        G[u][v] = min(G[u][v], w);
    }
    dijkstra(1);
    if(dist[n] == INF) cout << -1 << endl;
    else cout << dist[n] << endl;
    return 0;
}

使用堆优化

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

using namespace std;

const int N = 150005;
const int INF = 0x3f3f3f3f;

typedef pair<int, int> PII;

struct edge {
    int w;
    int to;
    int next; // 下一条边的编号
} edge[N];

int head[N];
int idx;
int dist[N];
bool vis[N];
int n, m;

void add(int u, int v, int w) {
    idx++;
    edge[idx].w = w;
    edge[idx].to = v;
    edge[idx].next = head[u];
    head[u] = idx;
}

void dijkstra(int s) {
    memset(dist, INF, sizeof(dist));
    dist[s] = 0;
    priority_queue<PII, vector<PII>, greater<PII>> heap;
    heap.push({0, s});
    while(heap.size()) {
        PII t = heap.top();
        heap.pop();
        int u = t.second;
        if(vis[u]) continue;
        vis[u] = true;
        for(int v = head[u]; v != -1; v = edge[v].next) {
            struct edge e = edge[v];
            if(dist[e.to] > dist[u] + e.w) {
                dist[e.to] = dist[u] + e.w;
                heap.push({dist[e.to], e.to});
            }
        }
    }
}

int main() {
    memset(head, -1, sizeof(head));
    cin >> n >> m;
    while(m--) {
        int u, v, w;
        cin >> u >> v >> w;
        add(u, v, w);
    }
    dijkstra(1);
    if(dist[n] == INF) cout << -1 << endl;
    else cout << dist[n] << endl;
    return 0;
}

Floyd —— 多源最短路

讲解

时间复杂度: O ( n 3 ) O(n^3) O(n3) n n n 是顶点数。

核心思想:以 i 为起点,j 为终点,i 到 j 的距离是否可以通过一个中转点 k 从而缩短距离。

Tips:j 不一定是 i 的邻接点。

image-20230113022820352

上图解释,从 A 点到 B 点,可以通过一个中转点 C 从而缩短距离。

适用场景:稠密图。

Java

public class Floyd {
    static final int INF = 0x7ffffff; 
    static final int MAX = 1010;
    static int[][] G = new int[MAX][MAX];
    static int n;

    public static void init() {
        for(int i = 1; i <= n; i++) {
            Arrays.fill(G[i], INF);
            G[i][i] = 0;
        }
    }

    public static void floyd() {
        for(int k = 1; k <= n; k++) { // 中转点
            for (int i = 1; i <= n; i++) { // 起点
                // 对于每个顶点 k 和任意顶点对 (i,j) i != j, k != i, k !=j
                // 若 G[i][j] > G[i][k] + G[k][j] 则将 G[i][j] 修改为 G[i][k] + G[k][j] 的值
                // 【记录路径可忽略】并且将 Path[i][j] 修改为 k(此步用于记录从某个顶点到某个顶点需要结果 k 顶点)
                if(i == k || G[i][k] == INF) continue;
                for (int j = 1; j <= n; j++) { // 终点
                    G[i][j] = Math.min(G[i][j], G[i][k] + G[k][j]);
                }
            }
        }
    }
}

C++

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

using namespace std;

const int N = 500;
const int INF = 0x3f3f3f3f;

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

void floyd() {
    for(int k = 1; k <= n; k++) {
        for(int i = 1; i <= n; i++) {
            if(i == k || G[i][k] == INF) continue;
            for(int j = 1; j <= n; j++) {
                G[i][j] = min(G[i][j], G[i][k] + G[k][j]);
            }
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/168795.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第五届字节跳动青训营 前端进阶学习笔记(三)CSS基本概念

文章目录前言CSS是什么1.CSS基本结构2.在面中使用CSS的方式3.CSS是如何工作的选择器1.通配选择器2.标签选择器3.id选择器4.类选择器5.属性选择器6.伪类选择器7.选择符颜色1.RGB颜色2.HSL颜色3.alpha透明度字体1.font-family2.font-size3.line-height4.text-align5.space6.text-…

从头搭建pytorch Docker镜像

目录前言正文从docker hub下载镜像创建容器并运行更新容器*安装python*安装anaconda安装pytorch参考文献&#xff1a;前言 此文不需要前言&#xff0c;请从正文开始 开始搭建 正文 默认大家都是有一定docker基础的&#xff0c;没有的话建议去花个20分钟学一下基础知识。相对…

如何利用极狐GitLab 轻松管理NPM依赖发布与更新?

本文来自&#xff1a; 任治桐 极狐(GitLab) 前端工程师 NPM 是 Node.js 的包管理工具&#xff0c;用来安装各种 Node.js 的扩展。本文将分享如何通过极狐GitLab&#xff0c;让 NPM 依赖发布更新更加快速和自动化&#xff0c;让你轻松管理依赖&#xff0c;拥有更多时间专注于核…

【Java|golang】1814. 统计一个数组中好对子的数目

给你一个数组 nums &#xff0c;数组中只包含非负整数。定义 rev(x) 的值为将整数 x 各个数字位反转得到的结果。比方说 rev(123) 321 &#xff0c; rev(120) 21 。我们称满足下面条件的下标对 (i, j) 是 好的 &#xff1a; 0 < i < j < nums.length nums[i] rev(…

算法之美~时间复杂度

时间复杂度 时间复杂度的全称是渐进时间复杂度&#xff0c;表示算法的执行时间与数据规模之间的增长关系1、只关注循环执行次数最多的一段代码2、加法法则&#xff1a;总复杂度等于量级最大的那段代码的复杂度3、乘法法则&#xff1a;嵌套代码的复杂度等于嵌套内外代码复杂度的…

文末有福利 | 零代码连接邮箱腾讯云企业网盘,附件管理超轻松

在日常工作中&#xff0c;想必大家每天都会收到各种各样的工作邮件&#xff0c;并且很多重要的文件材料也是通过邮件附件的形式来传输的&#xff0c;那么如何一站式管理这些文件&#xff0c;对于提高办公效率就至关重要了。关于邮件附件&#xff0c;相信大家也都碰到过这样的困…

【软件相关】Typora配置图片上传

文章目录0 前言1 确定需求2 开始配置2.1 软件储备2.2 插件安装2.3 gitee配置3 其他配置3.1 获取SMMS token参考链接0 前言 对于喜欢写Markdown文档的人来说&#xff0c;Typora无疑是一个写作利器&#xff0c;它有别于其他的Markdown软件&#xff0c;不是一边编辑一边渲染&#…

excel区分工时制度:如何计算996与955的工时差异

什么是996呢&#xff1f;是指早上9点上班&#xff0c;晚上9点下班&#xff0c;中午和晚上各有1小时吃饭时间&#xff0c;每周工作6天的工作模式。而955&#xff0c;也就是朝九晚五&#xff0c;中午就餐在工作时间内&#xff0c;但不能休息&#xff0c;共计8小时工作时间&#x…

[FUNC]在AHK中实现Pyhton的range函数

本文是用AutoHotkey复刻Python的range函数函数语法range(start, stop, step)参数说明&#xff1a;参数描述start计数从 start 开始。默认是从 0 开始。例如&#xff1a;range&#xff08;6&#xff09;等价于range(0,6)。stop计数到 stop 结束&#xff0c;但不包括 stop。例如&…

5、Ubuntu20常用操作_进程管理重定向和管道常用命令网络管理

进程管理 进程的概念 大家比较熟悉 Windows 下的可执行文件&#xff0c;就是那些扩展名为exe的文件。 大家知道&#xff0c;只需要鼠标双击这些程序&#xff0c; 就可以运行了。 程序运行起来后&#xff0c;我们把这个程序正在运行的 实例 称之为 进程 。 操作系统对每个进…

acwing86场周赛题解(模拟,dp,数学推导式)

目录 第一题&#xff1a;AcWing 4794. 健身 思路 核心代码 完整代码 第二题&#xff1a;4795. 安全区域 思路 核心代码 完整代码 第三题&#xff1a;4796. 删除序列 思路 核心代码 完整代码 谢谢您的阅读 第一题&#xff1a;AcWing 4794. 健身 4794. 健身 李华…

配置与管理DNS服务器

DNS概念 DNS是一种新的主机名称和IP地址转换机制&#xff0c;使用分层的分布式数据库来处理Internet上众多的主机和IP地址转换。当一个应用需要将域名翻译成为IP地址时&#xff0c;这个应用便成为域名系统的一个客户。这个客户将待翻译的域名放在一个DNS请求信息中&#xff0c;…

CHAPTER 10 Web服务与应用(二)

Web服务与应用10.1 Tomcat10.1.1 准备工作10.1.2 编写dockerfile10.1.3 创建tomcat用户和密码脚本文件10.1.4 编写启动脚本10.1.5 创建和测试镜像10.1.6 相关资源10.2 Jetty10.2.1 使用官方镜像10.2.2 相关资料10.3 LAMP10.3.1 使用官方镜像10.4 持续开发与管理10.4.1 Jenkins及…

[前端笔记——HTML介绍] 5.文档与网站架构

[前端笔记——HTML介绍] 5.文档与网站架构1.文档的基本组成部分&#xff08;1&#xff09;页眉&#xff08;2&#xff09;导航栏&#xff08;3&#xff09;主内容&#xff08;4&#xff09;侧边栏&#xff08;5&#xff09;页脚2.用于构建内容的HTML3.HTML布局元素细节3.1无语义…

205:vue+openlayer: 点击某feature,列表滑动,定位到相应的点的列表位置

第205个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+openlayers做一个互动,点击某个feature,在左侧的列表中显示出来,滚动条滑动,能显示在视觉区内。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果; 注意如果OpenStreetMap无法加载,请加载其…

HTB打靶(Active Directory 101 Resolute)

nmap扫描 nmap -A -T4 10.10.10.169 Starting Nmap 7.93 ( https://nmap.org ) at 2023-01-16 01:30 EST Stats: 0:00:04 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan SYN Stealth Scan Timing: About 74.65% done; ETC: 01:30 (0:00:01 remaining) St…

Maven学习(一):Maven简介及安装配置

Maven简介及安装配置一、Maven简介1.1、Maven是什么1.2、Maven的作用二、Maven安装配置2.1、大前提2.2、Maven下载2.3、windows版1、安装2、配置环境3、配置本地仓库2.4、mac版1、安装2、配置环境3、需要注意的点4、配置本地仓库一、Maven简介 1.1、Maven是什么 先对Maven做一…

从 Spectral Clustring 推导到 Regularized Diffusion Process

Spectral Clustring 参考&#xff1a;bilibili 机器学习-白板推导系列(二十二)-谱聚类&#xff08;Spectral Clustering&#xff09; Background 首先看一种数据分布&#xff1a; 对于以上分布的数据&#xff0c;可以直接利用K−meansK-meansK−means或者GMM&#xff08;高…

2、linux_CentOS_6_64位常用命令远程操作--yum云用不了_建议学习Ubuntu

Linux的概述 学习Linux之前先了解Unix Unix是一个强大的多用户、多任务操作系统。于1969年在AT&T的贝尔实验室开发。UNIX的商标权由国际开放标准组织&#xff08;The Open Group&#xff09;所拥有。UNIX操作系统是商业版&#xff0c;需要收费&#xff0c;价格比Microsof…

洞悉获客之道,林肯汽车开展高端社区精准营销俘获消费者芳心

一、出场即焦点 全新领航员诠释顶级美式豪华“强大的外部气场&#xff0c;肌肉与优雅完美结合”&#xff0c;一直以来&#xff0c;美式豪华汽车以沉稳、古典的高端奢华气质演绎“出场即焦点”的恢弘气场&#xff0c;吸引着无数精英人士为之着迷、追捧。2022 年&#xff0c;林肯…