洛谷P4779 单源最短路径与Dijkstra算法

(蒟蒻出品,欢迎指正)

Dijkstra算法(由于字母太多,以下统一用dij代替(逃

dij算法,使用广度优先搜索与贪心算法解决单源图的最短路径问题,不适用于有负权边的图。

时间复杂度:O(mlogn)//n为顶点数,m为边数。

算法思路:对于所需求解的图,首先假设任意两顶点之间距离为正无穷。然后开始加入边,更新当前该源点到其余顶点的最短距离,将没有加入已知集合的距离最小的点选出,确定此点与源点最短距离,重复上述操作直到所有已知条件加入集合。

实现步骤

1,确定当前待求最短路径的起点与终点;

2,将除起点外所有点加入未知集合,并将起点加入已知集合,直至确定该点到起点最短路径;

3,依次更新起点到i的距离dis[i];

4,将未知集合dis中与起点距离最小x的加入已知集合;

5,同Floyd算法思想,若起点与n间距离大于起点到x距离加x到n距离,更新dis[n];

6,重复以上步骤直到终点进入已知集合,输出答案;

当然若使用邻接矩阵存储是很慢的,为了优化时间及方便懒人,我们请出亲爱的优先队列与链式前向星帮助实现算法。

于是板子题:https://www.luogu.com.cn/problem/P4779应运而生。

 1 #include<bits/stdc++.h>
 2 #define ff(i,s,e) for(int i=s;i<=e;i++)
 3 using namespace std;
 4 inline int read(){
 5     register int x=0,f=1;
 6     register char ch=getchar();
 7     while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();}
 8     while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
 9     return x*f;
10 }
11 const int M=500002;
12 const int inf=0x3f3f3f3f;
13 int n,m,s;
14 int cnt,head[M];
15 long long dis[M];//s到i最短路径 
16 struct egde{
17     int to,nxt,w;
18 }e[M];
19 typedef pair<int,int> pir;//距离及当前所到点 
20 priority_queue<pir,vector<pir>,greater<pir> >q;//小根堆
21 void add(int u,int v,int w){//链式前向星 
22     e[++cnt].w=w;
23     e[cnt].to=v;
24     e[cnt].nxt=head[u];
25     head[u]=cnt;
26 }
27 void dij(int s){
28     ff(i,1,n) dis[i]=inf;//将s到每一个点的距离统一赋值正无穷 
29     dis[s]=0;//s到自己的距离为0 
30     q.push(pir(0,s));//将起点加入队列 
31     while(!q.empty()){
32         int f = q.top().first,u = q.top().second;//s到u最短距离为f 
34         q.pop();
35         if(f!=dis[u]) continue;//作用小到可以忽略的优化 
36         for(int i=head[u];i;i=e[i].nxt){//枚举点u可以到达的点更新最短路径 
37             int v=e[i].to,w=e[i].w;//当前所到下一个点及两点间权值 
38             if(dis[v]>dis[u]+w){
39                 dis[v]=dis[u]+w;//若以u为中转点到v路径更短,更新 
40                 q.push(pir(dis[v],v));//将当前已知最短路径入队 
41             }
42         }
43     }
44 }
45 int main(){
46     n=read();m=read();s=read();
47     ff(i,1,m){
48         int u,v,w;
49         u=read();v=read();w=read();
50         add(u,v,w); 
51     }
52     dij(s); 
53     ff(i,1,n) printf("%lld ",dis[i]);
54     return 0;
55 }

感谢大佬@硫化氢提供的模板。

posted @ 2022-02-11 23:12  专吃小仙女  阅读(92)  评论(0)    收藏  举报