单源最短路 狄克斯特拉算法
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两种工具,可以极大的节省空间以及算法实现中遍历搜索的时间,举一个例子
该图的邻接表表示为,具体实现可以看代码
解题思路大概就是把默认指向的轨道的权值设为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(迪杰斯特拉)算法