单源最短路 狄克斯特拉算法

Posted zlhdbk

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单源最短路 狄克斯特拉算法相关的知识,希望对你有一定的参考价值。

一般形式的用邻接矩阵来实现dijkstra效率比较低,我这里直接记录的是用邻接表的方法以及用优先队列加以应用。

首先解释什么是dijkstra算法

dijkstra算法

dijkstra算法适用于求单源最短路,即可以求出起点到其余各点之间的最短路。它的算法实现是一个不断更新的过程。

举一个最简单的例子,假设有这么一个图技术图片,红色表示权值,黑色表示4个点以及路径,我们假设起点为1,用d[i]来表示1到i的最短路,那么在第一轮的时候,d[2]=1,d[3]=1,d[4]=5,再下一轮的时候会对这个情况进行更新,结果为d[2]=1,d[3]=1,d[4]=4,以此类推,会一直更新到d[2]=1,d[3]=1,d[4]=3为止,所以我认为该算法是一个不断更新的过程。

邻接表表示法

邻接表表示法我们使用vector以及pair两种工具,可以极大的节省空间以及算法实现中遍历搜索的时间,举一个例子

技术图片该图的邻接表表示为技术图片,具体实现可以看代码

 

洛谷P1346

 

解题思路大概就是把默认指向的轨道的权值设为0,需要开关的轨道权值设为1。

 

 1 #include <iostream>
 2 #include <cstring>
 3 #include <string>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <stack>
 7 #include <stdio.h>
 8 #include <cmath>
 9 #include <string.h>
10 using namespace std;
11 #define ll long long
12 static const int WHITE=0;//未选
13 static const int GRAY=1;//备选
14 static const int BLACK=2;//已选
15 static const int INFTY=(1<<20);
16 int N,A,B;
17 vector<pair<int,int> > adj[105];//加权图的邻接表表示法
18 void dijkstra()
19 
20     priority_queue<pair<int,int> > que;//用优先队列,first表示路径成本,second表示路口
21     int color[105],d[105];
22     for(int i=1;i<=N;i++)//初始化
23     
24         d[i]=INFTY;
25         color[i]=WHITE;
26     
27     d[A]=0;//设置起点
28     que.push(make_pair(0,A));
29     color[A]=GRAY;
30     while (!que.empty())
31     
32         pair<int,int> f=que.top();
33         que.pop(); 
34         int u=f.second;
35         color[u]=BLACK;
36         if(d[u]<f.first*(-1))//取出最小值,若不是最短路则忽略
37         continue;
38         for(int j=0;j<adj[u].size();j++)//更新最短路
39         
40             int v=adj[u][j].first;
41             if(color[v]==BLACK)
42             continue;
43             if(d[v]>d[u]+adj[u][j].second)
44             
45                 d[v]=d[u]+adj[u][j].second;
46                 que.push(make_pair(d[v]*(-1),v));//因为优先队列默认优先较大值,所以乘以-1
47                 color[v]=GRAY;
48             
49         
50     
51     if(d[B]==INFTY)
52     cout<<"-1"<<endl;
53     else
54     
55         cout<<d[B]<<endl;
56     
57     
58 
59 int main()
60 
61     //freopen("C:\\\\Users\\\\16599\\\\Desktop\\\\in.txt","r",stdin);
62     scanf("%d%d%d",&N,&A,&B);
63     for(int i=1;i<=N;i++)
64     
65         int K,a;
66         scanf("%d",&K);
67         if(K!=0)//注意k可能为0
68         
69             scanf("%d",&a);
70             adj[i].push_back(make_pair(a,0));//表示第i个路口默认通向第a个路口,权值为0        
71         
72         for(int j=2;j<=K;j++)
73         
74             scanf("%d",&a);
75             adj[i].push_back(make_pair(a,1));//表示第i个路口通向第a个路口需要按开关,权值为1
76         
77     
78     dijkstra();
79     return 0;
80 

 

以上是关于单源最短路 狄克斯特拉算法的主要内容,如果未能解决你的问题,请参考以下文章

[C++]单源最短路径:迪杰斯特拉(Dijkstra)算法(贪心算法)

算法入门之单源最短路径算法:Dijkstra(迪杰斯特拉)算法

Dijkstra求解单源最短路径

数据结构 - 单源最短路径之迪杰斯特拉(Dijkstra)算法详解(Java)

单源最短路-dijkstra的算法

用小根堆实现dijkstra,求图的单源最短路径