zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    Matlab 绘制三维立体图(以地质异常体为例)
    Azure DevOps的variable group实现array和hashtable参数的传递
    Azure DevOps 利用rest api设置variable group
    Azure AADSTS7000215 其中一种问题的解决
    Power BI 实现实时更新Streaming Dataset
    AAD Service Principal获取azure user list (Microsoft Graph API)
    Matlab 沿三维任意方向切割CT图的仿真计算
    Azure Powershell script检测登陆并部署ARM Template
    Azure KeyVault设置策略和自动化添加secrets键值对
    Azure登陆的两种常见方式(user 和 service principal登陆)
  • 原文地址:https://www.cnblogs.com/XYYXP/p/dijkstra.html
Copyright © 2011-2022 走看看