单源最短路dijkstra O(nlog(n))
迪杰斯特拉算法:基于贪心思想的一种算法
算法思想:定义两个集合S1,S2; S1={已经遍历过的元素},S2={未遍历过的集合};
每次从未走过的集合S2中选取最近的元素k,以k点为中转,进行松弛操作,以确定是否有更优的路径;再将k放入S1中
若已知k为S2中最近的点,K可能经过S1中的点,经过S1中点的松弛操作,则可以知道当前k点的距离dist[k]一定是最短距离,则可以将k放入S1中,成为已完成遍历的确定了最短距离的元素,那么可以以k点为当前点对k可以到达的点进行松弛操作,以获得剩下点的更优值,则此时将可以将确定下一个中转点k',k’为松弛后的最短路径点,则类似可得,dist[k']一定为最短距离。
推导过程类似于数学归纳法;
优化:在寻找S2中dist最小值时可以采用stl库堆优化,使O(n^2)复杂度降为O(nlog(n));
1 struct node{ 2 int dis,name; 3 bool operator<(const node &x)const{ 4 return dis>x.dis; 5 } 6 }; 7 priority_queue<node>q;
完整代码:
1 #include<cmath> 2 #include<iostream> 3 #include<stdio.h> 4 #include<cstring> 5 #include<queue> 6 #define ll long long 7 #define INF 1234567890 8 const int N=1e4+10; const int M=5e5+10; 9 using namespace std; 10 int n,m,s,num=0,first[M],vis[N],dist[N]; 11 struct ed{ 12 int u,v,dis,next; 13 }edge[M]; 14 struct node{ 15 int dis,name; 16 bool operator<(const node &x)const{ 17 return dis>x.dis; 18 } 19 }; 20 priority_queue<node>q; 21 void addedge(int x,int y,int dis){ 22 edge[++num].u=x;edge[num].v=y;edge[num].dis=dis;edge[num].next=first[x];first[x]=num; 23 } 24 void dijkstra(int s){ 25 for (int i=1;i<=n;i++)dist[i]=INF; 26 dist[s]=0; 27 q.push(node{0,s}); 28 while (!q.empty()){ 29 node a=q.top(); 30 int u=a.name; 31 q.pop(); 32 if (!vis[u]){ 33 vis[u]=1; 34 for (int i=first[u];i;i=edge[i].next){ 35 int v=edge[i].v; 36 if (dist[v]>dist[u]+edge[i].dis){ 37 dist[v]=dist[u]+edge[i].dis; 38 q.push(node{dist[v],v}); 39 } 40 } 41 } 42 } 43 } 44 int main(){ 45 scanf("%d%d%d",&n,&m,&s); 46 for (int i=1;i<=m;i++){ 47 int x,y,dis;scanf("%d%d%d",&x,&y,&dis); 48 addedge(x,y,dis); 49 } 50 dijkstra(s); 51 for (int i=1;i<=n;i++){ 52 if (dist[i]==INF)printf("%d ",(1<<31)-1); 53 else printf("%d ",dist[i]); 54 } 55 }
缺陷:
dijkstra算法有一定缺陷,在有负环的情况下,也就是无最小路径时,无法判断出负环;如下图

在这种情况下,需要使用spfa判断负环.
浙公网安备 33010602011771号