先放代码:
#include <bits/stdc++.h>
using namespace std;
#define edgeN 5000005
#define pointN 1000005
#define infinity 2147483647
int pointnum,edgenum,startpoint,cnt(0),dis[pointN],vis[pointN],head[pointN];
struct node{
int distance_to_presentpoint,present_point;
inline bool operator <(const node &x) const{
return distance_to_presentpoint > x.present_point;
}
};
priority_queue<node>q;
//we usually use "pair< , >" here,why we use struct is to help us to understand the processes.
struct Edge{
int from,to,dis,next;
//"to" is the end spot of the edge.
//"next" is the edge after the present one.
}edge[edgeN];
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9') if(ch=='-')f=-1,ch=getchar();
while(ch>='0'&&ch<'9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
inline void add_edge(int from,int to,int dis){
edge[++cnt].from=from;//record the start spot of this edge.
edge[cnt].to=to;//record the end spot of this edge.
edge[cnt].dis=dis;//record the length of this edge.
edge[cnt].next=head[from];//record the next edge of this one.
head[from]=cnt;//put this edge into the head array.
}
inline void dijkstra(){
for(int i=1;i<=pointnum;i++) dis[i]=infinity;
dis[startpoint]=0;
/*super important*/q.push((node){0,startpoint});
while(!q.empty()){
//save the top of the heap(the shortest edge in the heap)and pop it off
node temp=q.top();
q.pop();
int nowposition=temp.present_point;
//if it hasn't been visited, visit it
if(vis[nowposition]==1) continue;
vis[nowposition]=1;
for(int i=head[nowposition];i;i=edge[i].next){
//search for all the edge of the top of the heap
int nextpoint=edge[i].to;
if(dis[nextpoint]>dis[nowposition]+edge[i].dis){
dis[nextpoint]=dis[nowposition]+edge[i].dis;
q.push((node){dis[nextpoint],nextpoint});//push the next point into the queue
}
}
}
}
int main(){
pointnum=read();edgenum=read();startpoint=read();
for(int i=1,frompoint,topoint,distance;i<=edgenum;i++){
frompoint=read();topoint=read();distance=read();
add_edge(frompoint,topoint,distance);
}
dijkstra();
for(int i=1;i<=pointnum;i++){
if(dis[i]!=infinity) printf("to point %d the shortest distance is %d\n",i,dis[i]);
printf("there is no way to point %d\n",i);
}
return 0;
}
例题见:洛谷:P4779 【模板】单源最短路径(标准版)
dijkstra算法
-
这是一种稍有缺陷的求单元最短路问题的常用算法,它可以求得每一个点到起点间的(当然肯定得是有通路的点)最小距离。
-
它的主要思想是从起点开始,对每一个点的出边进行比较,然后选择出边边权值最小的目标点入队并开始下一轮扩展。核心思想:贪心算法
-
其主要的缺陷是如果遇到两点间边权为负值时会出错(这一点Bellman-Ford可以完美解决),这一点需要注意。
-
其时间复杂度为O(n^2),通过优先队列(priority_queue)的优化后可以达到O(mlongn)。
-
上面的模板就是使用了堆优化的模板。并使用了邻接表储存,能更方便地处理数据较大的时候的空间问题,如果要用邻接矩阵储存,则部分代码如下:
//令邻接矩阵名为f,即:f[][];
//需要用到的数组有:bool vis[]/*标记点有没有走到过(入队过)*/;int dis[]/*记录每个点到起点的距离,在最开始时,除了直接与起点相连的以外,其他点的dis都为极大值*/;
//需要有的变量有:minn/*记录最小值*/,inf/*这个应该为const int,即定义的最大值,一般为0x3f3f3f3f*/,position/*当前在哪个点*/;
int Dijkstra(int start_point){
//初始化;
memset(vis,false,sizeof(vis);
for(int i=1;i<=点的总数;i++){
dis[i]=inf;
}
vis[start]=true;dis[start]=0;/*起点到自己的距离为0*/;
for(int i=1;i<=点的总数;i++){//初始化起点及与其相连的点;
dis[i]=f[start][i];
}
for(int i=1;i<=点的总数-1;i++){//由于起点为已知,故所需要遍历的点的个数为总数减一;
minn=inf;
for(int j=1;j<=点的总数;j++){//选择入队哪一个与这个点相连的点;
if(!vis[j]&&minn>dis[j]){
minn=dis[j];
position=j;
}
}
vis[position]=true;//将扩展的点标记为已经走过;
for(int j=1;j<=点的总数;j++){//由于新扩展出了点,更新dis[]的值;
if(!vis[j]) dis[j]=min(dis[j],dis[position]+f[position][j]);
}
}
return dis[n];
}
文章原创,请勿抄袭
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zlt_jackie/article/details/83450487
本文介绍了Dijkstra算法的基本思想和实现,通过邻接表来存储图,并给出了一个标准模板实例。文章指出,Dijkstra算法在处理负权重边时可能出错,而Bellman-Ford算法能有效解决这个问题。通过优先队列优化,Dijkstra算法的时间复杂度可以降低到O(mlogn)。文章提醒读者,当处理大量数据时,邻接表比邻接矩阵更节省空间。

被折叠的 条评论
为什么被折叠?



