Dijkstra算法及优化

Dijkstra算法策略为:
设置集合s存放已被访问的顶点,然后执行n次下面两个步骤(n为顶点数):

  1. 每次从集合v-s中选择与起点s的最短路径最小的一个顶点,访问并加入集合s中
  2. 之后,令顶点u为中介点,优化起点s与所有从u能到达的顶点v之间的最短路径

具体实现如下:

其中DFS函数用于输出访问的最短路径,其算法与DFS算法一致。

#include
#include
#include
#include
using namespace std;
const int MAXV=510;		//最大顶点数
const int INF=1000000;		//无穷大
struct Node{
	int v;
	int dis;		//v为边的目标顶点,dis为边权 
}; 
int n,m,st,ed; 		//n为顶点数,图G使用邻接表实现 ,st和ed分别为起点和终点 
int d[MAXV],minCost=INF;		//起点到达自身的距离为0 
int cost[MAXV][MAXV],G[MAXV][MAXV];
vector pre[MAXV];		//前驱 
vector tempPath,path;		//临时路径,最优路径 
bool vis[MAXV]={false};
void Dijkstra(int s){
	fill(d,d+MAXV,INF);		//fill函数将整个d数组赋为INF 
	d[s]=0;		//u使d[u]最小,min存放该最小的d[u] 
	for(int i=0;i0;i--){		//倒着访问
			//当前结点id,下个结点idnext 
			int id=tempPath[i],idNext=tempPath[i-1];
			tempCost+=cost[id][idNext];		//增加边id->idNext的边权 
		}
		if(tempCost=0;i--){
		printf("%d ",path[i]);		//倒着输出路径上的结点 
	}
	printf("%d %d\n",d[ed],minCost);		//最短距离,最短路径上的花费 
	return 0;
}

从复杂度来看,主要是外层循环O(n)与内层循环寻找最小的d[u]需要O(n),枚举v需要O(adj[u].size)产生的。对于整个程序来说,时间复杂度为O((n^2+m)).

优化算法:

寻找最小的d[u]不必达到O(n)的复杂度,而可以使用堆优化来降低复杂度。直接使用STL中的优先队列,这样使用邻接表实现的Dijkstra算法的时间复杂度可以降为O(n*logn+m).

#include
#include
#include
#include
#include
using namespace std;
const int MAXV=510;		//最大顶点数
const int INF=1000000;		//无穷大
struct Node{
	int v;
	int dis;		//v为边的目标顶点,dis为边权 
	friend bool operator <(Node f1,Node f2){	//默认从大到小输出,所以反向重载 
		return f1.dis>f2.dis;
	}
}; 
int n,m,st,ed; 		//n为顶点数,图G使用邻接表实现 ,st和ed分别为起点和终点 
int d[MAXV],minCost=INF;		//起点到达自身的距离为0 
int cost[MAXV][MAXV],G[MAXV][MAXV];
vector pre[MAXV];		//前驱 
vector tempPath,path;		//临时路径,最优路径 
bool vis[MAXV]={false};
priority_queue q; 
void Dijkstra(int s){
	fill(d,d+MAXV,INF);		//fill函数将整个d数组赋为INF 
	d[s]=0;
	q.push({s,0});		//u使d[u]最小,min存放该最小的d[u] 
	for(int i=0;i0;i--){		//倒着访问
			//当前结点id,下个结点idnext 
			int id=tempPath[i],idNext=tempPath[i-1];
			tempCost+=cost[id][idNext];		//增加边id->idNext的边权 
		}
		if(tempCost=0;i--){
		printf("%d ",path[i]);		//倒着输出路径上的结点 
	}
	printf("%d %d\n",d[ed],minCost);		//最短距离,最短路径上的花费 
	return 0;
}

你可能感兴趣的:(C/C++)