单源最短路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;
View Code

 

完整代码:

 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 }
View Code

 

缺陷:

dijkstra算法有一定缺陷,在有负环的情况下,也就是无最小路径时,无法判断出负环;如下图

在这种情况下,需要使用spfa判断负环.