• Dijkstra算法浅理解


    22.11.10更新:之前大一初学时尝试“严谨”证明,但现在来看只是感性陈述了一番。上个星期,在算法课上学习了算法导论上从路径松弛性质出发的证明,回顾一下自己之前的思路,同时完善之前的公式表达。


    数学建模书中的算法描述:

    设所考虑的图为 N = N ( V , A , W ) N=N(V, A, W) N=N(V,A,W),其中 V = v 1 , v 2 , … , v n V={v_1,v_2,…,v_n} V=v1,v2,vn,即顶点个数 ∣ V ∣ = n |V|=n V=n E E E为弧边的集合,其弧边的条数为 ∣ E ∣ = m |E|=m E=m W = ( w i j ) n ∗ n W=(w_{ij})_{n*n} W=(wij)nn为权值邻接矩阵, w i j w{ij} wij为边 ( v i , v j ) (v_i,v_j) (vi,vj)的权值,满足 w i j ≥ 0 w_{ij}\geq0 wij0,如果 ( v i , v j ) ∉ E (v_i,v_j)∉E (vi,vj)/E,则 w i j = ∞ w_{ij}=∞ wij=.
    v 1 v_1 v1为起点(源点),记 d ( v j ) d(v_j) d(vj)表示从源点 v 1 v_1 v1 v j v_j vj只允许经过已选出的顶点的最短路的权值(路长),即最短路上的点均属于已选出的顶点集合。

    算法步骤:

    1、输入权值邻接矩阵 W W W,令 d ( v 1 ) = 0 , d ( v j ) = w 1 j , j ∈ [ 2 , n ] , S = v 1 , R = V / S 1 = v 2 , … , v n d(v_1)=0,d(v_j)=w_{1j},j∈[2,n],S={v_1},R=V/S_1={v_2,…,v_n} d(v1)=0,d(vj)=w1j,j[2,n],S=v1,R=V/S1=v2,,vn( S S S中的点给永久记号, R R R中的点給临时记号);

    (标记这一步将点分成了两个集合, S S S集合给永久记号意味着对应点 v k v_k vk对应的 d ( v k ) d(v_k) d(vk)不会再改变)
    2、在 R R R中取一点 v k v_k vk,使得 d ( v k ) = m i n { d ( v j ) , v j ∈ R } d(v_k) = min\{d(v_j),v_j∈R\} d(vk)=min{d(vj),vjR},如果 d ( v k ) = + ∞ d(v_k)=+∞ d(vk)=+,停止向下搜索,即从 v 1 v_1 v1 R R R中的点没有路,否则转第三步;
    3、令 S = S ∪ v k , R = R / v k S=S∪{v_k},R=R/{v_k} S=Svk,R=R/vk,( k k k改为永久记号)。如果 R = ∅ R=∅ R=,结束,所有各点的最短路都已经求得;否则转第四步;
    4、对于每一个 v j ∈ R v_j∈R vjR,修正 d ( v j ) = m i n { d ( v j ) , d ( v k ) + w k j } d(v_j)=min\{d(v_j),d(v_k)+w_{kj}\} d(vj)=min{d(vj),d(vk)+wkj},返回第二步。


    理解1:为什么可以求得最短路?

    算法实际上运用了动态规划的思想,每次我从 R R R集合中选取一个离 v 1 v_1 v1的最近点 v k v_k vk,用它去修正 d ( ) d() d()这个以已选取点(就是 S S S集合中的点)作为内点的最短路数组,每次这个内点集合都会增加一个点,最后所有的点(不可到达点除外)都会被选进这个内点集合,我们所得到的 d ( ) d() d()就是以图上所有点为内点的和 v 1 v_1 v1之间最短路数组,而这也就是 v 1 v_1 v1的所有单源最短路数组,是 v 1 v_1 v1和所有其他点的最短路数组。

    理解2:为什么每次选进S集合的点,都能保证已经求得 v 1 v_1 v1和它的最短路?

    首先我们要清楚一个事实,即每次选进 S S S集合的点 v k v_k vk,它所对应的 d ( v k ) d(v_k) d(vk)大于任意已经选进 S S S集合的点的 d d d,换一种说法,用 v k v_k vk修正后 d d d不小于 d ( v k ) d(v_k) d(vk),因为修正的时候 d ( v j ) = m i n { d ( v j ) , d ( v k ) + w k j } , d ( v j ) ≥ d ( v k ) d(v_j) = min\{d(v_j),d(v_k)+w_{kj}\},d(v_j)\geq d(v_k) d(vj)=min{d(vj),d(vk)+wkj},d(vj)d(vk)
    若我们选进 S S S集合的点,并未求得 v 1 v_1 v1到它的最短路(反证法),则说明到该点的最短路内点不只有之前已选进 S S S集合的点。设最短路还包括内点 a , a ∈ R a,a∈R a,aR,这样的话,在之后的步骤中,我们会以 d ( a ) d(a) d(a)修正 d ( v k ) , v k ∈ S d(v_k),v_k∈S d(vk),vkS,而根据之前我们的结论 d ( v k ) ≤ d ( a ) d(v_k)\leq d(a) d(vk)d(a) d ( v k ) d(v_k) d(vk)并不会被修改。所以每次选进 S S S集合的点,我们都能保证已经求得 v 1 v_1 v1和它的最短路。


    理解1中提及dp,实质上松弛操作就是一步递推,用公式表达就是递推公式。理解2说明了点 v v v选进集合 S S S之后, d ( v ) d(v) d(v)不再变化,有点算导中证循环不变式的意味,但是无法保证 d ( v ) d(v) d(v)就是最短路,没有阐述为何收敛,这是否可以通过前面dp公式补充?dp公式的正确性最终应通过收敛性保证吧。

  • 相关阅读:
    Bean生命周期
    Netty框架详解
    【dgl学习】dgl.canonical_etypes函数解析
    [树上倍增]Eezie and Pie 2022牛客多校第6场 B
    【每日一题】补档 CF1792C. Min Max Sort | 思维 | 简单
    Mock.js之Element-ui搭建首页导航与左侧菜单
    前端秘法基础式(HTML)(第二卷)
    xml转换成txt (VOC转换为YOLO)
    【LeetCode热题100】--240.搜索二维矩阵II
    Go分布式缓存 HTTP 服务端(day3)
  • 原文地址:https://blog.csdn.net/qq_23096319/article/details/127800204