zoukankan      html  css  js  c++  java
  • 迪杰斯特拉(Dijkstra)算法描述及理解

    Dijkstra算法是一种计算单源最短无负边路径问题的常用算法之一,时间复杂度为O(n2)

    算法描述如下:dis[v]表示s到v的距离,pre[v]为v的前驱结点,用以输出路径,vis[v]表示该点最短路径是否已经确认

    初始化:dis[v]=INT dis[s]=0 pre[s]=0

      执行n次

        在没有确定的点中找到一个路径最短的,并修改为已经确认

        通过这个点修改其他所有没有确定的点

        直到所有点已经确认为最短路径,退出循环

    现在证明算法的正确性:

    首先,我们说明两条性质:

    1.确定任何一个点为最短路径时,前驱p一定已经是最短路径(假设源点的前驱是它本身)。

    2.任意时刻在还没有确定最短路径的点的集合中路径最短的点就是可以被确定的点。

    稍微证明一下这两条性质(反证法):

    证明1:假如前驱p还不是最短路径,那么显然当p是最短路径时到当前节点的路径更短,即不是最短路径的节点所确定的节点一定不是最短路径(好像很显然)

    证明2:为了方便描述,我们定义已经确定的点为白点,没有确定的点为蓝点。若是蓝点中路径最短x还不能确定为白点,那么x的最短路径上必定存在一个蓝点y。即dis[x]>dis[y]+edge[y][x]。而dis[y]处于两种状态:

    (1)dis[y]已经是y点的最短路径,那么显然与dis[x]为蓝点中最短的相矛盾。

    (2)dis[y]还不是y点的最短路径,那么它的前驱显然是另外一个蓝点,即dis[y]>=dis[x](这里省略了一些步骤,不过自己稍微想一下,我觉得挺显然的),也矛盾。

    综上,性质2得证。

    回过头再看我们的算法:

    在刚开始的时候,首先确定的最短路(就是直接和源点相连的点)进入白点集合,满足性质1,2。

    此后每个过程都满足以上两个性质,所以算法正确。

    算法实现:

     

     1 memset(vis,0,sizeof(vis));
     2 vis[s]=1;
     3 dis[s]=0;
     4 for(int i=1;i<n;i++)
     5 {
     6     int m=INT_MAX;
     7     int k=0;
     8     for(int j=1;j<=n;j++)
     9     {
    10         if(!vis[j] && dis[j]<m)
    11         {
    12             m=dis[j];
    13             k=j;
    14         }
    15     }
    16     if(k==0)
    17     break;
    18     vis[k]=1;
    19     for(int j=1;j<=n;j++)
    20     {
    21         if(dis[k]+e[k][j]<dis[j])
    22         dis[j]=dis[k]+e[k]; 
    23     }
    24 }
    View Code

     

  • 相关阅读:
    K3s+Jetson Nano,在边缘端实现实时视频分析!
    15分钟连接Jetson Nano与K8S,轻松搭建机器学习集群
    配置高可用K3s集群完全攻略
    K3s+Sysdig,8分钟部署并保护集群安全!
    1款工具助力Rancher HA快速部署,极速提升研发测试效率
    连刷40道题,告别动态规划,谈谈我的经验
    直通BAT算法精讲视频教程分享
    关于三次握手和四次挥手,面试官想听到怎样的回答?
    Redisson 分布式锁实战与 watch dog 机制解读
    Spring 注解动态数据源设计实践
  • 原文地址:https://www.cnblogs.com/qgmzbry/p/10684574.html
Copyright © 2011-2022 走看看