邻接表实现dijkstra算法

先放代码:

#include 
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_queueq;
//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算法

  1. 这是一种稍有缺陷的求单元最短路问题的常用算法,它可以求得每一个点到起点间的(当然肯定得是有通路的点)最小距离。

  2. 它的主要思想是从起点开始,对每一个点的出边进行比较,然后选择出边边权值最小的目标点入队并开始下一轮扩展。核心思想:贪心算法

  3. 其主要的缺陷是如果遇到两点间边权为负值时会出错(这一点Bellman-Ford可以完美解决),这一点需要注意。

  4. 其时间复杂度为O(n^2),通过优先队列(priority_queue)的优化后可以达到O(mlongn)。

  5. 上面的模板就是使用了堆优化的模板。并使用了邻接表储存,能更方便地处理数据较大的时候的空间问题,如果要用邻接矩阵储存,则部分代码如下:

	//令邻接矩阵名为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];
	}

文章原创,请勿抄袭

你可能感兴趣的:(最短路算法)