最短路相关思想总结

news2024/11/25 10:12:36

dijkstra—所有边均为正权边

1.稠密图

dijkstra()1

算法思想

将所有的点读入邻接表
外层n次循环
每次找到最近的点,记录这个点的访问状态,使用这个点对其他的点进行更新,最后返回最短路
为什么要记录每个点的状态?我不能重复搜这个点吗???
我们的目的是找到最短路径,不能知道原地转,需要向前走,我们不能走回头路

算法步骤:

#include<iostream>
#include<cstring>
using namespace std;
const int N=510;
int g[N][N],d[N],st[N];
//st记录是否被访问过
int n,m;

int dijkstra()
{
    d[1]=0;
    for(int i=1;i<=n;i++)
    {
        int t=-1;
        for(int j=1;j<=n;j++)
            if(!st[j]&&(t==-1||d[t]>d[j]))
                t=j;
        st[t]=true;
        for(int j=1;j<=n;j++)
            if(d[j]>d[t]+g[t][j])
                d[j]=d[t]+g[t][j];
    }
    return d[n];
}
int main()
{
    cin>>n>>m;
    memset(d,0x3f,sizeof(d));
    memset(g,0x3f,sizeof(g));
    while(m--)
    {
        int a,b,c;
        cin>>a>>b>>c;
        g[a][b]=min(g[a][b],c);
    }
    int t=dijkstra();
    if(t==0x3f3f3f3f) puts("-1");
    else printf("%d\n",t);
    return 0;
}

2.稀疏图

dijkstra()2

算法思想

将所有的点读入,因为是邻接表,还是正权边—>dijkstra算法
dijkstra算法需要找到每次的最短的边,所以需要使用优先队列来快速取出最短的距离

算法步骤以及实现

#include<iostream>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int N=3e5+10;
int h[N],e[N],ne[N],idx,w[N],d[N],st[N];
//st表示是否被搜过
int n,m;
typedef pair<int,int> PII;

void add(int a,int b,int c)
{
    e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
int dijkstra()
{
	//每次拿出最近的点,所以排序的时候需要将距离进行排序
	//监测他是否被搜过
	//如果被搜过直接跳过,没有就进行更新
	//后面被更新的点,没有被搜过那么将他放进堆中
    priority_queue<PII,vector<PII>,greater<PII>> p;
    d[1]=0;
    p.push({0,1});
    while(p.size())
    {
        auto t=p.top();
        p.pop();
        int pos=t.second,dis=t.first;
        if(st[pos]) continue;//如果被搜过就不在搜了
        st[pos]=true;//如果被搜索过了,更新成true
        for(int i=h[pos];~i;i=ne[i])
        {
            int j=e[i];
            if(d[j]>dis+w[i]) d[j]=dis+w[i],p.push({d[j],j});
        }
    }
    return d[n];
}
int main()
{
    cin>>n>>m;
    //读入数据并初始化
    memset(d,0x3f,sizeof(d));
    memset(h,-1,sizeof(h));
    while(m--)
    {
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);//有向图
    }
    int t=dijkstra();
    if(t==0x3f3f3f3f) t=-1;
    printf("%d\n",t);
    
    return 0;
}

bellman_fold—存在负权边

在这里插入图片描述

算法思想

我们对边进行存储,对所有的边进行访问,使用上次的距离进行更新

算法步骤以及实现

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=10010;
struct Edge
{
    int a,b,c;
}edge[N];
int n,m,k;
int d[N],last[N];//last记录上次的距离

int bellman_fold()
{
	//在不超过k次的情况下,进行搜索
    for(int i=0;i<k;i++)
    {
    	//每次记录上次的距离
        memcpy(last,d,sizeof(d));
        for(int j=0;j<m;j++)
        {
            auto e=edge[j];
            d[e.b]=min(d[e.b],last[e.a]+e.c);
        }
    }
    return d[n];
}
int main()
{
    cin>>n>>m>>k;
    //使用结构体进行存储
    for(int i=0;i<m;i++) cin>>edge[i].a>>edge[i].b>>edge[i].c;
    //对距离进行初始化
    memset(d,0x3f,sizeof(d));
    d[1]=0;
    
    int t=bellman_fold();
    if(t>0x3f3f3f3f/2) puts("impossible");
    else printf("%d",t);
    
    return 0;
}

spfa算法—存在负权边

在这里插入图片描述

算法思想

spfa是对bellman_fold算法的升级,将出发点加入队列中(队列中的点都是变化的点)
持续从队列中取出一个点,记录这个点没在队列中,判断他的临边是否需要改变如果改变->加入队列并记录在队列中的状态

算法步骤以及实现

#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int N=1e5+10;
int h[N],e[N],ne[N],idx,d[N],st[N],w[N];
//st表示是否在队列中
int n,m;

void add(int a,int b,int c)
{
    e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
int spfa()
{
    d[1]=0;
    queue<int> q;
    q.push(1);
    st[1]=true;
    while(q.size())
    {
        int t=q.front();
        q.pop();
        st[t]=false;//表示没有在队列中
        
        for(int i=h[t];~i;i=ne[i])
        {
            int j=e[i];
            if(d[j]>d[t]+w[i])//表示需要更新的点,将更新的点加入队列中
            {
                d[j]=d[t]+w[i];
                if(!st[j])//将没有在队列中的点加入队列中
                {
                    q.push(j);
                    st[j]=true;
                }
            }
        }
    }
    return d[n];
}
int main()
{
    memset(h,-1,sizeof(h));
    cin>>n>>m;
    for(int i=0;i<m;i++) 
    {
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
    }
    memset(d,0x3f,sizeof(d));
    int t=spfa();
    if(t==0x3f3f3f3f) puts("impossible");
    else printf("%d\n",t);
    
    return 0;
}

堆优化版的spfa算法

在这里插入图片描述

算法思想

spfa算法是bellman_fold算法的进化
判负环的基本方法是spfa
将数据读入,因为不知道那个点是负环的起点所有每个点都有可能–>将所有点加入队列,如果距离更小,更新距离并将此点加入队列

算法步骤以及实现

#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int N=1e4+10;
//d不需要进行初始化,如果存在负权边那么一定会改变
int d[N],st[N],w[N],h[N],e[N],ne[N],idx,cnt[N];
int n,m;

void add(int a,int b,int c)
{
    e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
bool spfa()
{
    queue<int> q;
    for(int i=1;i<=n;i++) q.push(i),st[i]=true;
    
    while(q.size())
    {
        int t=q.front();
        q.pop();
        st[t]=false;
        for(int i=h[t];~i;i=ne[i])
        {
            int j=e[i];
            if(d[j]>d[t]+w[i])
            {
                d[j]=d[t]+w[i];
                cnt[j]=cnt[t]+1;
                //当点的个数大于等于n的时候,证明已经是出现负环了
                if(cnt[j]>=n) return true;
                if(!st[j]) 
                {
                    st[j]=true;
                    q.push(j);
                }
            }
        }
    }
    return false;
}
int main()
{
    cin>>n>>m;
    memset(h,-1,sizeof(h));
    //memset(d,0x3f,sizeof(d));

    while(m--)
    {
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
    }
    if(spfa()) puts("Yes");
    else puts("No");
    
    return 0;
}

floyd算法—多源汇—不存在负权回路

在这里插入图片描述

算法思想

稠密图,使用邻接矩阵来存
因为是多源汇,所有每个点都可能使起点,所以在初始化的时候需要注意将每个点的自己到自己的距离初始化为0

算法步骤以及实现

#include<cstring>
#include<iostream>
using namespace std;
const int N=210,INF=0x3f3f3f3f;
int d[N][N];
int n,m,k;

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()
{
    cin>>n>>m>>k;
    //多源汇
    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;
        cin>>a>>b>>c;
        d[a][b]=min(d[a][b],c);
    }
    floyd();
    while(k--)
    {
        int a,b;
        cin>>a>>b;
        if(d[a][b]>INF/2) puts("impossible");
        else printf("%d\n",d[a][b]);
    }
    
    
    return 0;
}
以上是我的一些暂时的理解,可能有些不恰当的地方,
以后如果发现了更好的理解方式,会回来的。

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

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

相关文章

面对AI冲击,技术人才该如何考核?

一天下午&#xff0c;在与知名企业的技术交流会议室里&#xff0c;一位兄弟企业的CTO 小力苦笑着&#xff0c;分享了一个技术招聘的故事&#xff1a; “我们有个高级工程师&#xff0c;为了搞定MySQL三个表Join的问题&#xff0c;搞了一整天都研究不出来。结果他尝试将表结构扔…

【C++进阶】继承、多态的详解(继承篇)

【C进阶】继承、多态的详解&#xff08;继承篇&#xff09; 目录 【C进阶】继承、多态的详解&#xff08;继承篇&#xff09;继承的概念及定义继承的概念继承的定义定义格式继承关系和访问限定符继承基类成员访问方式的变化 基类和派生类对象赋值转换继承中的作用域派生类的默认…

你不能访问此共享文件夹因为你组织的安全策略

我在windows 10中尝试访问没有密码的共享文件只报错如下&#xff1a; 解决办法 运气中执行 gpedit.msc来启动本地组策略编辑器。 这样设置完成后&#xff0c;就可以在运行中输入 \\192.168.199.1\可以访问共享的文件了。 参考 https://zhuanlan.zhihu.com/p/164721714…

HashMap 二十一问

1&#xff1a;HashMap 的数据结构&#xff1f; A&#xff1a;哈希表结构&#xff08;链表散列&#xff1a;数组链表&#xff09;实现&#xff0c;结合数组和链表的优点。当链表长度超过 8 时&#xff0c;链表转换为红黑树。transient Node<K,V>[] table; 2&#xff1a;…

QT QtXlsx安装使用

QtXlsx介绍 QtXlsx是一个可以读取和写入Excel文件的库。它不需要Microsoft Excel&#xff0c;可以在Qt5支持的任何平台上使用。 这里一定是需要QT5支持的。 须知安装QtXlsx时&#xff0c;需要下载perl 1.安装perl 这里选择官网下载安装即可。 官网地址&#xff1a;https://p…

Android应用开发(35)SufaceView基本用法

Android应用开发学习笔记——目录索引 参考Android官网&#xff1a;https://developer.android.com/reference/android/view/SurfaceView 一、SurfaceView简介 SurfaceView派生自View&#xff0c;提供嵌入视图层次结构内部的专用绘图表面&#xff0c;SurfaceView可以在主线程之…

开学第一课什么时候播出2023年在哪里用手机在线观看开学第一课高清直播入口

往期《开学第一课》什么时候播出&#xff1f; 《开学第一课》是一年一度面向全国中小学生的大型公益节目&#xff0c;从2008年起于每年9月1日播出&#xff0c;最近一期是2022年9月1日20:00播出&#xff1b; 2023年《开学第一课》什么时候播出&#xff1f; 根据往期播出时间预…

Spring Task入门案例

Spring Task 是Spring框架提供的任务调度工具&#xff0c;可以按照约定的时间自动执行某个代码逻辑。 定位&#xff1a;定时任务框架 作用&#xff1a;定时自动执行某段Java代码 强调&#xff1a;只要是需要定时处理的场景都可以使用Spring Task 1. cron表达式 cron表达式…

安装docker和案例复现

安装环境 1.安装docker #输入命令 yum install -y yum-utils 安装下载docker的工具包 yum install -y yum-utils # 设置阿里docker镜像仓库地址 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo yum install -y docker-ce d…

【JavaSpring】注解开发

注解开发定义bean 不指定名称 package org.example.service.impl;import org.example.dao.BookDao; import org.example.service.BookService; import org.springframework.stereotype.Component;Component public class BookServiceimpl implements BookService {private Bo…

[JAVAee]多线程环境下:HashTable, HashMap, ConcurrentHashMap之间的区别

HashMap在多线程环境下是不安全的,只能在单线程下使用. 多线程下安全的只有: HashTableConcurrentHashMap HashTable HashTable在多线程环境下安全的原因是,给其的get与put方法都使用synchronized修饰了,被锁的对象是整个HashTable,只要有线程对此HashTable操作就上锁,其他…

Yolov8-pose关键点检测:loss系列 | 手把手教程,多loss设计提升关键点提取性能

💡💡💡本文解决什么问题:手把手教会你v8PoseLoss 多loss设计,提升关键点检测 Yolov8-Pose关键点检测专栏介绍:https://blog.csdn.net/m0_63774211/category_12398833.html ✨✨✨手把手教你从数据标记到生成适合Yolov8-pose的yolo数据集; 🚀🚀🚀模型性能提升…

修改第三方组件默认样式

深度选择器 修改el-input的样式&#xff1a; <el-input class"input-area"></el-input>查看DOM结构&#xff1a; 原本使用 /deep/ 但是可能不兼容 使用 :deep .input-area {:deep(.el-input__inner){background-color: blue;} }将 input 框背景色改为…

09-1_Qt 5.9 C++开发指南_Qchart概述

Qt Charts 可以很方便地绘制常见的折线图、柱状图、饼图等图表&#xff0c;不用自己耗费时间和精力开发绘图组件或使用第三方组件了。 本章首先介绍 Qt Charts 的基本特点和功能&#xff0c;以画折线图为例详细说明 Qt Charts 各主要部件的操作方法&#xff0c;再介绍各种常用…

竞赛项目 酒店评价的情感倾向分析

前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 酒店评价的情感倾向分析 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng-senior/post…

【MySQL--->环境配置】

文章目录 [TOC](文章目录) 一、卸载已存在数据库软件二、获取yum源并安装三、启动并登录四、文件配置五、链接服务器选项 一、卸载已存在数据库软件 用ps -axj |grep miadb或者ps -axj |grep mysql查询是否存在这两个启动的应用程序,如果有就将其关闭,以mysql为例:systemctl s…

史上最强,Jenkins插件实现多个Job并行后再触发Job详细,一篇贯通...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 在利用Jenkins来自…

linux安装wkhtmltopdf(清晰明了)

概述 在公司项目中使用到 wkhtmltopdf 转换PDF&#xff0c;由于 wkhtmltox-0.12.5 版本 echarts 图形虚线样式&#xff0c;需要升级 wkhtmltox-0.12.6 版本来解决。 官网地址 wkhtmltopdf &#xff1a;https://wkhtmltopdf.org/ windows 安装 下载流程及安装流程 进入官…

Redis—集群

目录标题 主从复制第一次同步命令传播分担主服务器压力增量复制总结面试题什么是Redis主从复制Redis主从复制的原理Redis主从复制的优点Redis主从复制的缺点Redis主从复制的配置步骤Redis主从复制的同步策略主从节点是长还是短连接判断某个节点是否正常工作主从复制架构中&…

linux学习(地址空间)[7]

地址空间 在子进程中修改变量值&#xff0c;不会和父进程同步&#xff0c;但是地址空间相同&#xff08;此地址不是物理内存的地址&#xff09;&#xff08;而是虚拟地址–线性地址&#xff09; 几乎所有的语言&#xff0c;如果有地址的概念&#xff0c;这个地址一定是虚拟地…