• 2019中山纪念中学夏令营-Day14 图论初步【dijkstra算法求最短路】


    Dijkstra是我学会的第一个最短路算法,为什么不先去学SPFA呢?因为我在luogu上翻到了一张比较神奇的图:

    关于SPFA

    -它死了

    以及网上还有各位大佬的经验告诉我:SPFA这玩意很容易被卡。

    于是我就决定学习Dijkstra

    结构体存边(链式前向星)+优先队列(堆)+Dijkstra求最短路

    详细解析都在代码里。

    下面附上代码

     1 //2019.08.14 XYYXP第一次写dijkstra最短路算法 于中山纪念中学 
     2 //模板题:Luogu P3371,P4779 
     3 #include <cstdio>
     4 #include <queue>
     5 #include <algorithm>
     6 #define rr register
     7 using namespace std;
     8 const int inf = 2147483647;
     9 int n,m,s,head[500005],tot,dis[100005],used[100005];
    10 //定义全局变量和最大值(inf) 
    11 struct Edge{
    12     int nxt,to,length;
    13 }edge[500005];
    14 //用结构体存边,nxt表示这条边起点连着的上一条边,to表示这条边通往哪个点,length表示边权 
    15 struct state {
    16     int val, pos;
    17     
    18     bool operator < (const state &tmp) const 
    19     {
    20         return val > tmp.val;
    21     }
    22     //重载运算符(重载小于号成大于号,用于大根堆变小根堆) 
    23 };
    24 //定义一个结构体存点,pos表示当前点编号,val表示当前点到起点的最短路长度 
    25 state makestate(int _pos,int _val)
    26 {
    27     state tmp;
    28     tmp.pos=_pos;
    29     tmp.val=_val;
    30     return tmp;
    31 }
    32 //一个结构体函数,新建一个state类型的结构体 
    33 void add(int x,int y,int z)
    34 {
    35     tot++;
    36     edge[tot].to=y;
    37     edge[tot].nxt=head[x];
    38     edge[tot].length=z;
    39     head[x]=tot;
    40 }
    41 //加边函数,表示x到y之间有一条权值为z的边 
    42 priority_queue <state> heap;
    43 //新建一个优先队列(STL库函数) 
    44 void dijkstra(int st)
    45 {
    46     for(rr int i=1;i<=n;i++)
    47         dis[i]=inf;
    48     //初始化起点到各个点的最短路为inf 
    49     dis[st]=0;
    50     heap.push(makestate(st,dis[st]));
    51     //初始化起点,起点入队 
    52     while(!heap.empty())
    53     {
    54         int u = heap.top().pos;
    55         heap.pop();
    56         //取出优先队列中最小的点,用来更新最短路 
    57         if(used[u])
    58             continue;
    59         used[u]=true;
    60         //判断和标记当前点是否被已经用来更新过 
    61         for(rr int i=head[u];i;i=edge[i].nxt)
    62         {
    63             int &v=edge[i].to;
    64             //引用 v=edge[i].to; 
    65             if(dis[v] > dis[u]+edge[i].length)
    66             {
    67                 dis[v] = dis[u]+edge[i].length;
    68                 //更新最短路 
    69                 heap.push(makestate(v,dis[v]));
    70                 //将更新完的最短路入队 
    71             }
    72         }
    73     }
    74 }
    75 
    76 int main()
    77 {
    78     int x,y,z;
    79     scanf("%d %d %d",&n,&m,&s);
    80     for(rr int i=1;i<=m;i++)
    81     {
    82         scanf("%d %d %d",&x,&y,&z);
    83         add(x,y,z);
    84     }
    85     //读入并建边 
    86     dijkstra(s);
    87     //调用dijkstra算法函数求单源最短路 
    88     for(rr int i=1;i<=n;i++)
    89         printf("%d ",dis[i]);
    90     //输出起点到各点的最短路 
    91 }

    The End

  • 相关阅读:
    CDH Mysql元数据库升级
    greenplum gpcheckperf 命令(GP集群压力测试)
    centos7 升级openssh到openssh-8.0p1版本(转)
    正则表达式中的 1
    Docker系列03—Docker 基础入门
    Docker系列01—容器的发展历程
    二进制安装部署 4 kubernetes集群---超详细教程
    kubernetes系列11—PV和PVC详解
    kubernetes系列10—存储卷详解
    kubernetes系列09—Ingress控制器详解
  • 原文地址:https://www.cnblogs.com/XYYXP/p/dijkstra.html
Copyright © 2020-2023  润新知