首页 > 其他分享 >最短路径问题

最短路径问题

时间:2023-11-14 21:11:55浏览次数:35  
标签:结点 dist 路径 最短 问题 集合 顶点

有权图的单源最短路算法

Dijkstra 算法

给定任何一个非负权边的图$v_0,....v_n $ ,要找到\(v_0\)到\(v_m\)的最短路径
设已找到的最短路径的结点集合为\(S\) ,未找到最短路径的结点集合为\(T\) ,\(V_0\)到所有结点的最短路径数组为\(dist\),初始状态\(dist[0] = 0, dist[1..n] = \infty\)

重复以下步骤:

  1. 从集合\(T\)中基于\(dist\)中找到当前已知的最短路径结点\(v_x\) 加入集合\(S\)中
  2. 基于\(v_x\)所相连的结点 更新$dist $数组,即 $ dist\left[ v_y \right] = min(dist\left[ v_y \right], dist\left[ v_x \right] + W(v_x,v_y)) $
  3. 重复1、2步骤直到所有结点都加入集合\(S\)

证明

设算法迭代每一次加入集合\(S\)的结点依次为\(v_{x_1},v_{x_2} ....v_{x_k}\)证明每一次加入\(S\)中的结点都是最短路径

  1. 第一次加入的结点\(v_{x_1}\)显然是最短路径。
  2. 假设第K次加入的结点\(v_{x_k}\)为最短路径,此时集合S为\(\left\{ v_{x_1},v_{x_2},...v_{x_k} \right\}\),现证明根据算法运行第 k + 1次加入的结点\(v_{x_{k+1}}\)仍为最短路径。
  3. 反证,假设加入的\(v_{x_{k+1}}\)不是最短路径,即存在另外一条路径为最短路径,设\(v_u\)为该路径中不在集合\(S\)的第一个结点,则\(dist\left[ v_u \right] < dist\left[ v_{x_{k+1}} \right]\),dijkstra的算法的第一个步骤是每次从集合T中基于\(dist\)选取距离最小的结点加入集合\(S\),因此\(dist\left[ v_{x_{k+1}} \right] <= dist\left[ v_u \right]\),因此产生矛盾。得证。

路径一定是按照递增(非递减)的顺序生成,且经过收录后经过更新不会改变已收录的点最短路径
如果收录后将\(dist\)更新得更小,收录点必落在被更新点的路径上,则他必然先被收录

每次从未收录的顶点中选一个dist最小的收录(必为最短路径)贪心

邻接表+优先队列 实现Dijkstra算法

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
#define INFINITY 10000

typedef int Vertex;
struct Edge {
    int Adj;	//邻接点
    int Weight;
};

vector<vector<Edge>> G;
vector<int> dist;
vector<Vertex> path;
int Nv, Ne;

void buildGraph() {
    cin >> Nv >> Ne;
    G.resize(Nv + 1); //调整邻接表的大小为n
    
    for (int i = 0; i < Ne; i++) {
        int v1, v2, w; // v1和v2表示边的两个端点,w表示边的权重
        cin >> v1 >> v2 >> w;
        G[v1].push_back(Edge{ v2, w }); // 在v1的邻接表中添加一条边(v1, v2, w)
        G[v2].push_back(Edge{ v1, w }); // 在v2的邻接表中添加一条边(v2, v1, w)
    }
}
struct MyType {
    Vertex index;
    int dist;
    friend bool operator < (const MyType& a, const MyType& b) {
        return a.dist > b.dist;	//重载小于号,变成最小堆
    }
};


void dijkstra(Vertex cur) {
    dist = vector<int>(Nv, INFINITY);	//将dist初始化为正无穷,使得以后能够进行更新
    path = vector<Vertex>(Nv, -1);
    vector<bool>collected(Nv, false);

    dist[cur] = 0;

    priority_queue<MyType>H;
    H.push({cur, dist[cur]});

    while (!H.empty()) {
        Vertex V = H.top().index;
        H.pop();
        collected[V] = true;

        for (Vertex W = 0; W < G[V].size(); W++) {
            Vertex next = G[V][W].Adj;	//找到cur的邻接点
            if (!collected[next]) {		//如果当前点未被收录
                if (dist[V] + G[V][W].Weight < dist[next]) {	//且dist可以更新得更小
                    dist[next] = dist[V] + G[V][W].Weight;
                    path[next] = V;
                    H.push({ next,dist[next] });
                }
            }
        }
    }
}

注意:

Dijkstra算法不适用负权

Dijkstra算法核心思想是每次从未确定最短路径的顶点集合中选出距离源点最近的一个顶点,然后以该顶点为中介,更新其他顶点到源点的距离。
这个过程中,Dijkstra算法会维护一个不变量,即已确定最短路径的顶点集合中的任意顶点到源点的距离都是最短的,而未确定最短路径的顶点集合中的任意顶点到源点的距离都是不小于最短的。

如果图中存在负权边,那么负权边会破坏Dijkstra算法的不变量,使得已确定最短路径的顶点集合中的某些顶点到源点的距离不是最短的,而未确定最短路径的顶点集合中的某些顶点到源点的距离是最短的。这样就会导致Dijkstra算法选错中介顶点,从而得到错误的结果。

标签:结点,dist,路径,最短,问题,集合,顶点
From: https://www.cnblogs.com/Cynthia32/p/17832581.html

相关文章

  • RK3588解决无法音乐/相册等无法同步问题
    RK3588解决无法音乐/相册等无法同步问题 背景 最近在做一个项目的时候发现音乐APP无法自动识别设备中的音频,这个APP是芯片厂商写的,可能由于年代久远,有这种奇怪的bug。复现步骤如下:1、使用adbpush音频文件到/sdcard/Music/文件夹下或使用文件管理器从外部设备(如U盘)将音频......
  • js处理前端页面复选框多页复选同时生效的问题
    虽然是后端开发,但在实际的工作中难免会碰到一些前端相关的任务需要自己处理,下面就是本人开发工作中处理的前端相关分页复选的问题。总结一下,以备日后重复遇到:<scripttype="text/javascript">//初始化数据$(function(){$('#queryButton').removeAttr('disabled'......
  • 如何解决“当前上下文中不存在名称“XXXXXXXX””的问题
    原文链接:http://t.zoukankan.com/s5689412-p-9848122.html项目中的.cshtml文件出现编译调试一切正常,但是在设计时查看出现下面的提示时:错误CS0103当前上下文中不存在名称“ViewBag”XXXXXXXXXXXXXXXXIndex.cshtml2活动的错误CS0103当前上下文......
  • git拉取失败问题
    错误提示:ITISPOSSIBLETHATSOMEONEISDOINGSOMETHINGNASTY!Someonecouldbeeavesdroppingonyourightnow(man-in-the-middleattack)!Itisalsopossiblethatahostkeyhasjustbeenchanged.ThefingerprintfortheRSAkeysentbytheremotehostisSHA25......
  • 妙用 FutureTask + 线程池:轻松解决接口超时问题!
    来源:blog.csdn.net/qq_44384533/article/details/112324224之前红包权益领取查询的接口超时了,因为有用户订购的权益有点多解决方案用线程池+FutureTask将1个查询拆分成多个小查询选择FutureTask是因为它具有仅执行1次run()方法的特性(即使有多次调用也只执行1次),避免了重复查......
  • 【溶解度工具】上海道宁为您带来了解溶解度、分散性、扩散、色谱等问题的强大而实用的
      高度参数化的UNIFAC技术可以提供出色的预测COSMO-RS方法的量子化学基础可以在明确的公式中进行精确预测Abraham参数和NRTL-SAC也各有其独特的功能优秀的配方师会使用正确的工具来完成手头的工作  如果您必须只使用一种工具那么它应该是HSP......
  • 关于使用dataBinding找不到控件ID的问题
    前提提要:知道真相的我真的难受在应用级别gradle配置中开启了dataBinding在布局文件中使用了layoutactivity_main_dessert.xml是我的xml文件名使用databing的过程如下结果:大面积的控件ID找不到,真的难受解决方式:就是这里,名字太相似了,完全没注意......
  • Vue3调用Element-plus涉及子组件v-model双向绑定props问题
    Vue3调用Element-plus涉及子组件v-model双向绑定props问题在Vue3调用Element-plus的el-dialog组件时,碰到个很有意思的问题,el-dialog的属性值v-model直接控制对话框的显示与否,点击关闭对话框和遮罩区域,组件内部会自动更改v-model的值为false来关闭对话框。问题在于当组件作为子组......
  • 解决 keras 首次装载预训练模型VGG16 时下载失败问题
    解决:Exception:URLfetchfailureonhttps://storage.googleapis.com/tensorflow/keras-applications/vgg16/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5:None--[Errno104]Connectionresetbypeer解决方案:1、先将数据集单独下载下来:models/vgg16_weights_tf_d......
  • requests 在 Python 3.2 中使用 OAuth 导入失败的问题与解决方案
    问题背景在Python3.2中,尝试使用Request的OAuth支持时,遇到了OAuth导入失败的问题。以下代码:importrequestsfromrequests.authimportOAuth1url='https://api.twitter.com/1/account/settings.json'queryoauth=OAuth1('client_key','client_secret',......