图论之最短路算法模板总结

来个大致的分类:

朴素的迪杰斯特拉:

实现:

我们让s表示当前已经确定的最短距离的点,我们找到一个不在s中的距离最近的点t,并用t来更新其他的点。

下面是AC代码:

#include<bits/stdc++.h>
using namespace std;
//求1---n的最短路(用邻接矩阵存储)
const int N=510;
int n,m;
int g[N][N];
int dis[N];
bool st[N];
int dij()
{
    memset(dis,0x3f,sizeof(dis));
    dis[1]=0;
    for(int i=0;i<n;i++)//一共n次
    {
        int t=-1;
        //找最近的点
        for(int j=1;j<=n;j++)
        {
            if(!st[j]&&(t==-1||dis[t]>dis[j])) t=j;
        }
        st[t]=1;
        //更新
        for(int j=1;j<=n;j++)
        {
            dis[j]=min(dis[j],dis[t]+g[t][j]);
        }
        
    }
    if(dis[n]==1e8) return -1;
    return dis[n];
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(i==j) g[i][j]=0;
            else g[i][j]=1e8;
        }
    }
    while(m--)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        g[a][b]=min(g[a][b],c);
    }
    cout<<dij();
}

堆优化的迪杰斯特拉:

#include<bits/stdc++.h>
using namespace std;
const int N=100100;
int n,m;
int h[N],w[N],e[N],ne[N],id;
int dis[N];
bool st[N];
typedef pair<int,int> pii;
void add(int a,int b,int c)
{
    e[id]=b,w[id]=c,ne[id]=h[a],h[a]=id++;
}
int dij()
{
    memset(dis,0x3f,sizeof(dis));
    dis[1]=0;
    priority_queue<pii,vector<pii>,greater<pii>> heap;
    heap.push({0,1});
    
    while(!heap.empty())
    {
        auto t=heap.top();
        heap.pop();
        int ver=t.second,dist=t.first;
        if(st[ver]) continue;
        st[ver]=1;
        for(int i=h[ver];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(dis[j]>dist+w[i])
            {
                dis[j]=dist+w[i];
                heap.push({dis[j],j});
            }
        }
    }
    if(dis[n]==0x3f3f3f3f) return -1;
    return dis[n];
}
int main()
{
    cin>>n>>m;
    memset(h,-1,sizeof(h));
    while(m--)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        add(a,b,c);
    }
    cout<<dij();
}

Bellman-Ford算法:

实现:循环n次,每一次循环所有边并更新。

注意:有负权的可能没有最短路,我们最外面循环了k次,他的含义是最多经过k条边的最短路,因此若循环超过该次数说明有环,这样子就是有负环了,但是有负环不一定说明答案不存在比方说一个与答案路径无关的负环,因此一般无法用该算法判断。

下面是AC代码(只可以走k条边):

#include<bits/stdc++.h>
using namespace std;
const int N=510,M=100010;
int n,m,k,f;
int dis[N],backup[N];
struct node
{
    int a,b,w;
    
}edge[M];
int bel()
{
    memset(dis,0x3f,sizeof(dis));
    dis[1]=0;
    for(int i=0;i<k;i++)
    {
        memcpy(backup,dis,sizeof(dis));//防止更新时用同一回的更新
        for(int j=0;j<m;j++)
        {
            int a=edge[j].a,b=edge[j].b,w=edge[j].w;
            dis[b]=min(dis[b],backup[a]+w);
        }
    }
    if(dis[n]>0x3f3f3f3f/2){
        f=1;
        return -1;
    } 
    //有负权边
    return dis[n];
}
int main()
{
    cin>>n>>m>>k;
    for(int i=0;i<m;i++)
    {
        int a,b,w;
        scanf("%d%d%d",&a,&b,&w);
        edge[i]={a,b,w};
    }
    int t=bel();
    if(t==-1&&f) cout<<"impossible";
    else cout<<t;
}

SPFA算法:

#include<bits/stdc++.h>
using namespace std;
const int N=100100;
int n,m;
int h[N],w[N],e[N],ne[N],id;
int dis[N];
bool st[N];
void add(int a,int b,int c)
{
    e[id]=b,w[id]=c,ne[id]=h[a],h[a]=id++;
}
int spfa()
{   memset(dis,0x3f,sizeof(dis));
    dis[1]=0;
    queue<int> q;
    q.push(1);
    st[1]=1;
    while(q.size())
    {
        int t=q.front();
        q.pop();
        st[t]=0;
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(dis[j]>dis[t]+w[i])
            {
                dis[j]=dis[t]+w[i];
                if(!st[j])
                {
                    q.push(j);
                    st[j]=1;
                }
            }
        }
    }
    if(dis[n]==0x3f3f3f3f) return -1;
    return dis[n];
}
int main()
{
    cin>>n>>m;
    memset(h,-1,sizeof(h));
    while(m--)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        add(a,b,c);
    }
    int t=spfa();
    if(t==-1) cout<<"impossible";
    else cout<<t;
}

SPFA求负环:

同时维护cnt[x]表示当前最短路的边数,我们cnt[x]=cnt[t]+1,若有cnt[x]>=n,说明有了负环。

下面是AC代码:

#include<bits/stdc++.h>
using namespace std;
const int N=100100;
int n,m;
int h[N],w[N],e[N],ne[N],id;
int dis[N],cnt[N];
bool st[N];
void add(int a,int b,int c)
{
    e[id]=b,w[id]=c,ne[id]=h[a],h[a]=id++;
}
int spfa()
{   
    queue<int> q;
    for(int i=1;i<=n;i++)
    {
        st[i]=1;
        q.push(i);
    }//相当于一个超级源点
    while(q.size())
    {
        int t=q.front();
        q.pop();
        st[t]=0;
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(dis[j]>dis[t]+w[i])
            {
                dis[j]=dis[t]+w[i];
                cnt[j]=cnt[t]+1;
                if(cnt[j]>=n) return 1;
                if(!st[j])
                {
                    q.push(j);
                    st[j]=1;
                }
            }
        }
    }
    return 0;
}
int main()
{
    cin>>n>>m;
    memset(h,-1,sizeof(h));
    while(m--)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        add(a,b,c);
    }
    int t=spfa();
    if(t==1) cout<<"Yes";
    else cout<<"No";
}

Floyd算法:

#include<bits/stdc++.h>
using namespace std;
const int N = 210, INF = 1e9;
int n, m, q;
int d[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 ++ )
                d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}

int main()
{
    scanf("%d%d%d", &n, &m, &q);

    for (int i = 1; i <= n; i ++ )
        for (int j = 1; j <= n; j ++ )
            if (i == j) d[i][j] = 0;
            else d[i][j] = INF;
    while (m -- )
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        d[a][b] = min(d[a][b], c);
    }

    floyd();
    while (q -- )
    {
        int a, b;
        scanf("%d%d", &a, &b);

        int t = d[a][b];
        if (t > INF / 2) puts("impossible");
        else printf("%d\n", t);
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《Spring-MVC》系列文章目录

简介 Spring MVC是一种基于Java的实现MVC设计模式的请求驱动类型的轻量级Web框架&#xff0c;它通过把Model&#xff08;模型&#xff09;、View&#xff08;视图&#xff09;、Controller&#xff08;控制器&#xff09;分离&#xff0c;将web层进行职责解耦&#xff0c;把复杂…

Getting started - 英文版 - English Version

&#x1f917; ApiHug {Postman|Swagger|Api...} 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱&#xff0c;有温度&#xff0c;有质量&#xff0c;有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace This pa…

在不同操作系统上自动生成Protocol Buffers的Java语言包的方法

各语言的Protocol Buffers文件都需要通过protoc来生成&#xff0c;这个动作往往需要手动输入命令完成。本文介绍的方法&#xff0c;将借助Maven来实现自动化生成工作。这样开发者只要专注于proto的定义&#xff0c;且不用将生成的文件上传到代码仓库&#xff0c;从而降低开发的…

Tracecat:开源 SOAR

Tracecat 是一个面向安全团队的开源自动化平台。 开发人员认为&#xff0c;每个人都应该可以使用安全自动化&#xff0c;特别是人手不足的中小型团队。 核心功能、用户界面和日常工作流程基于一流安全团队的现有最佳实践。 使用专门的人工智能模型来标记、总结和丰富警报。 …

【软件开发规范篇】JAVA后端开发编码注释规范

作者介绍&#xff1a;本人笔名姑苏老陈&#xff0c;从事JAVA开发工作十多年了&#xff0c;带过大学刚毕业的实习生&#xff0c;也带过技术团队。最近有个朋友的表弟&#xff0c;马上要大学毕业了&#xff0c;想从事JAVA开发工作&#xff0c;但不知道从何处入手。于是&#xff0…

20240502在WIN11下显示桌面

20240502在WIN11下显示桌面 2024/5/2 15:06 百度&#xff1a;WIN11 状态栏 右键 显示桌面 在WIN10下&#xff0c;可以在状态栏点击右键→“显示桌面”来最小化全部窗口&#xff0c;特别是我打开的浏览器的巨多的窗口&#xff01; 但是在WIN11下&#xff0c;这个【显示桌面】怎…

2024五一杯数学建模B题思路代码文章教学-交通需求规划与可达率问题

交通需求规划与可达率问题 问题总结&#xff1a; 问题一&#xff1a;在一个小型交通网络中&#xff0c;给定的起点和终点之间的交通需求需分配到相应路径上。目标是最大化任意一条路段出现突发状况时的交通需求期望可达率。 问题二&#xff1a;在一个较大的交通网络中&#xff…

Linux-进程调度器

1. 前言 在计算机中&#xff0c;进程的数量远多于cpu的数量&#xff0c;所以就存在&#xff0c;多个进程抢占一个cpu的情况&#xff0c;所以就需要一套规则&#xff0c;决定这些进程被处理的顺序&#xff0c;这就叫做进程调度。 在我的简单理解下&#xff0c;其实就是把进程放…

普乐蛙景区vr体验馆VR游乐场设备身历其境体验

小编给大家推荐一款gao坪效产品【暗黑战车】&#xff0c;一次6人同乘&#xff0c;炫酷外观、强大性能和丰富内容适合各个年龄层客群&#xff0c;紧张刺激的VR体验让玩家沉浸在元宇宙的魅力中&#xff0c;无论是节假日还是平日&#xff0c;景区商场助力门店提高客流量和营收~ ◆…

实验三 .Java 语言继承和多态应用练习 (课内实验)

一、实验目的 本次实验的主要目的是通过查看程序的运行结果及实际编写程序&#xff0c;练习使用 Java 语言的继承特性。 二、实验要求 1. 认真阅读实验内容&#xff0c;完成实验内容所设的题目 2. 能够应用多种编辑环境编写 JAVA 语言源程序 3. 认真体会多态与继承的作用…

B+树详解与实现

B树详解与实现 一、引言二、B树的定义三、B树的插入四、B树的删除五、B树的查找效率六、B树与B树的区别和联系 一、引言 B树是一种树数据结构&#xff0c;通常用于数据库和操作系统的文件系统中。它的特点是能够保持数据稳定有序&#xff0c;其插入与修改拥有较稳定的对数时间…

WebGL/Cesium 大空间相机抖动 RTE(Relative to Eye)实现原理简析

在浏览器中渲染大尺寸 3D 模型&#xff1a;Speckle 处理空间抖动的方法 WebGL/Cesium 大空间相机抖动 RTE(Relative to Eye)实现原理简析 注: 相机空间和视图空间 概念等效混用 1、实现的关键代码 const material new THREE.RawShaderMaterial({uniforms: {cameraPostion: {…

【Qt QML】用CMake管理Qt工程

CMake是一个开源、跨平台的工具系列&#xff0c;用于构建、测试和打包软件。CMake使用简单的独立配置文件来控制软件编译过程。与许多跨平台系统不同&#xff0c;CMake被设计为与本地构建环境结合使用。 下面我们在CMake项目中使用Qt的最基本方法。首先&#xff0c;创建一个基本…

如何解决pycharm创建项目报错 Error occurred when installing package ‘requests‘. Details.

&#x1f42f; 如何解决PyCharm创建项目时的包安装错误&#xff1a;‘requests’ &#x1f6e0;️ 文章目录 &#x1f42f; 如何解决PyCharm创建项目时的包安装错误&#xff1a;requests &#x1f6e0;️摘要引言正文&#x1f4d8; **问题分析**&#x1f680; **更换Python版本…

OpenCV 实现重新映射(53)

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV 实现霍夫圆变换(52) 下一篇 :OpenCV实现仿射变换(54) 目标 在本教程中&#xff0c;您将学习如何&#xff1a; 一个。使用 OpenCV 函数 cv&#xff1a;&#xff1a;remap 实现简…

Java Web 开发 - 掌握拦截器和监听器

目录 深入了解Java Web的拦截器和监听器 拦截器&#xff08;Interceptor&#xff09; 拦截器的使用场景 拦截器实例 思维导图 ​编辑 监听器&#xff08;Listener&#xff09; 监听器的使用场景 监听器类型 监听器实例 思维导图​编辑 总结 深入了解Java Web的拦截器…

C——双向链表

一.链表的概念及结构 链表是一种物理存储单元上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的。什么意思呢&#xff1f;意思就是链表在物理结构上不一定是连续的&#xff0c;但在逻辑结构上一定是连续的。链表是由一个一个的节点连…

uniapp0基础编写安卓原生插件和调用第三方jar包和编写语音播报插件之使用jar包插件

前言 如果你不会编写安卓插件,你可以先看看我之前零基础的文章(uniapp0基础编写安卓原生插件和调用第三方jar包和编写语音播报插件之零基础编写安卓插件), 我们使用第三方包,jar包编写安卓插件 开始 把依赖包,放到某个模块的/libs目录(myTestPlug/libs) 还要到build…

java-函数式编程-函数对象

定义 什么是合格的函数&#xff1f;无论多少次执行函数&#xff0c;只要输入一样&#xff0c;输出就不会改变 对象方法的简写 其实在类中&#xff0c;我们很多参数中都有一个this&#xff0c;被隐藏传入了 函数也可以作为对象传递&#xff0c;lambda就是很好的例子 函数式接口中…

ROS实操:通信机制的实现

最近闲来无事&#xff0c;打算重温了一下ROS方面的相关知识。先前的学习都是一带而过&#xff0c;发现差不多都忘了&#xff0c;学习的不够深入。因此&#xff0c;在重温的同时&#xff0c;写下了这篇关于ROS架构的学习博客。 上一篇博客的链接为&#xff1a;ROS架构的学习【No…