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

 

posted @ 2019-08-14 17:02  XYYXP  阅读(208)  评论(0编辑  收藏  举报