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

news2024/10/5 23:30:13

来个大致的分类:

朴素的迪杰斯特拉:

实现:

我们让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);
    }
}

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

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

相关文章

C++之const用法小结

在C中&#xff0c;const关键字具有多种用法&#xff0c;主要用于声明常量&#xff0c;确保某些变量的值在程序运行期间不会被修改。以下是const在C中的一些常见用法&#xff1a; 1.声明常量&#xff1a; 使用const声明的变量是常量&#xff0c;其值在初始化后不能再被修改。 …

关于海康相机和镜头参数的记录

对比MV-CS020-10UC和大家用的最多的MV-CS016-10UC 其实前者适合雷达站使用&#xff0c;后者适合自瞄使用 一&#xff1a;MV-CS020-10UC的参数 二&#xff1a;对比 三&#xff1a;海康镜头选型工具

mysql从入门到起飞+面试基础题

mysql基础 MySQL基础 企业面试题1 代码 select m.id,m.num from ( select t.id as id,count(1) num from ( select ra.requester_id as id from RequestAccepted raunion all select ra.accepter_id as id from RequestAccepted ra ) t group by t.id ) m group by id ord…

C++学习第十八课:STL中的`string`类深度解析

C学习第十八课&#xff1a;STL中的string类深度解析 在C标准模板库&#xff08;STL&#xff09;中&#xff0c;std::string是一个提供了大量功能和操作的类&#xff0c;用于处理和存储字符串数据。std::string不仅包含了传统的C风格字符串&#xff08;如char*&#xff09;所提…

算法二:DOM - 将DOM节点元素转换成JSON字符串

题目&#xff1a; 将DOM节点元素转换成JSON的格式 例如 <div class"root"><div class"child1"><p></p></div><span></span><div><div><p></p></div></div><p></…

XY_RE复现(六)

馒头 考数据结构的好像 有一个建树的函数 __int64 __fastcall initHuffmanTree(void **a1) {__int64 v1; // rcx__int64 v2; // rdxchar v4; // [rsp27h] [rbp-9h]int j; // [rsp28h] [rbp-8h]int i; // [rsp2Ch] [rbp-4h]*a1 malloc(0x3C0ui64);for ( i 1; i < 47; i )…

OpenGL 入门(一)—— OpenGL 基础

1、OpenGL 基础知识 1.1 OpenGL 简介 OpenGL&#xff08;Open Graphics Library&#xff09;是图形领域的工业标准&#xff0c;是一套跨编程语言、跨平台、专业的图形编程&#xff08;软件&#xff09;接口。它用于二维、三维图像&#xff0c;是一个功能强大&#xff0c;调用…

一个C++小程序调试过程记录

Top 20 C Projects With Source Code [2024 Update]https://www.interviewbit.com/blog/cpp-projects/ 这个网页有一些简单的C程序的源码&#xff0c;闲来无事&#xff0c;把第一个程序&#xff08;Bookshop Management System Using C&#xff09;的源码下载了下来。 源文件…

在 Vue.js 2.x 中使用 WebSocket 与 Spring Boot 2.7 实现通信

前言&#xff1a;近期在研究远程遥控空调&#xff0c;需要通过接口记录前端的一些动作&#xff0c;那么前端需要实现主动通知接口&#xff0c;并接收来自接口的通知。 一、方案 通过在Vue.js 2.x 中使用 WebSocket 与 Spring Boot 2.7 实现通信&#xff0c;使用 STOMP&#xf…

【openLooKeng集成Hive连接器完整过程】

【openLooKeng集成Hive连接器完整过程】 一、摘要二、正文2.1 环境说明2.2 Hadoop安装2.2.1. 准备工作2.2.2 在协调节点coordinator上进行安装hadoop2.2.3、将Hadoop安装目录分发到从节点worker2.2.4、在协调节点coordinator上启动hadoop集群2.3 MySQL安装2.4 Hive安装及基本操…

LabVIEW智能变电站监控系统设计与实现

LabVIEW智能变电站监控系统设计与实现 随着电力系统和智能化技术的快速发展&#xff0c;建立一个高效、可靠的变电站监控系统显得尤为重要。通过分析变电站监控系统的需求&#xff0c;设计了一个基于LabVIEW软件的监控平台。该平台利用虚拟仪器技术、传感器技术和无线传输技术…

从C到Py:Python的异常处理

本篇文章中我们将简单讲解一下有关Python中的异常处理&#xff0c;既有在代码中有显式表达的异常处理语法&#xff0c;还包括Pycharm手动调试的简单操作。 目录 Python异常处理 1、try-except结构 ​编辑 2、try-except-else结构 raise抛出异常 常见异常类型 Pycharm程序…

神经网络中常见的激活函数:理解与实践

神经网络中常见的激活函数&#xff1a;理解与实践 在神经网络中&#xff0c;激活函数是一个非常重要的组成部分&#xff0c;它为神经元引入了非线性特性&#xff0c;使得神经网络可以拟合各种复杂的函数关系。本文将介绍9种常见的激活函数&#xff0c;包括它们的概述、公式以及…

安卓中级控件(图形、选择按钮、文本输入、对话框)

图形定制 图形Drawable Android把所有能够显示的图形都抽象为Drawable类&#xff08;可绘制的&#xff09;。这里的图形不止是图片&#xff0c;还包括色块、画板、背景等。 包含图片在内的图形文件放在res目录的各个drawable目录下&#xff0c;其中drawable目录一般保存描述性…

相机知识的补充

一&#xff1a;镜头 1.1MP的概念 相机中MP的意思是指百万像素。MP是mega pixel的缩写。mega意为一百万&#xff0c;mega pixel 指意为100万像素。“像素”是相机感光器件上的感光最小单位。就像是光学相机的感光胶片的银粒一样&#xff0c;记忆在数码相机的“胶片”&#xff…

windows 驱动开发-DMA技术(二)

前面描述了DMA技术中适配器相关的部分以及DMA的分类&#xff0c;接下来看一下系统具体在支持两种DMA时候的操作的细微差别。 此处解释一下Scatter/Gather&#xff0c;这个也翻译为散点/收集&#xff0c;是指指示设备能够读取或写入内存中的任何区域&#xff0c;而不仅仅是特定…

YOLO系列改进,自研模块助力涨点

目录 一、原理 二、代码 三、添加到YOLOv5中 一、原理 论文地址:

LiveCD镜像文件的定制化

最近想要定制化一款属于自己的LiveCD镜像文件&#xff0c;并且里边封装好所需要的软件程序&#xff0c;本文将会记录具体的操作步骤&#xff0c;供有需要的人参考借鉴。 环境说明&#xff1a; 环境配置说明配置参数编码环境Centos7.9LiveCD文件CentOS-7-livecd-x86_64.iso 附…

袁庭新ES系列18节|Spring Data Elasticsearch高级

前言 这一章节袁老师将带领同学们来学习Spring Data Elasticsearch高级操作相关的内容。我们继续来探索SDE是如何将原始操作Elasticsearch的客户端API进行封装的&#xff0c;以及通过Spring Data Elasticsearch如何来操作ES。准备好了吗&#xff1f;我们继续来探索ES的内容。 …

探索AI工具的巅峰:个人体验与深度剖析

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…