一、邻接矩阵,时间复杂度O(n^2)
//Dijkstra的最短路算法
#include<bits/stdc++.h>
using namespace std;
const int MAX_N=10000;
const int MAX_M=100000;
const int inf=0x3f3f3f3f;
struct edge{
int v,w,next;
}e[MAX_M];
int p[MAX_N],eid,n;
void mapinit(){
memset(p,-1,sizeof(p));
eid=0;
}
void insert(int u,int v,int w){//插入带权有向边
e[eid].v=v;
e[eid].w=w;
e[eid].next=p[u];
p[u]=eid++;
}
void insert2(int u,int v,int w){//插入带权双向边
insert(u,v,w);
insert(v,u,w);
}
int dist[MAX_N];//存储单源最短路的结果
bool vst[MAX_N];//标记每个顶点是否在集合U中
bool dijkstra(int s){
memset(vst,0,sizeof(vst));
memset(dist,0x3f,sizeof(dist));
dist[s]=0;
for(int i=0;i<n;++i){
int v,min_w=inf;//记录dist最小的顶点编号和dist值
for(int j=0;j<n;++j){
if(!vst[j]&&dist[j]<minw){
minw=dist[j];
v=j;
}
}
if(min_w==inf){
return false;//没有可用的点,算法结束,说明有顶点无法从源点到达
}
vst[v]=true;//将顶点v加入集合U中
for(int j=p[v];j+1;j=e[j].next){
//如果和v相邻的顶点x满足dist[v]+w(v,x)<dist[x],则更新dist[x],这一操作被称为松弛操作
int x=e[j].v;
if(!vst[x]&&dist[v]+e[j].w<dist[x]){
dist[x]=dist[v]+e[j].w;
}
}
}
return true;//源点可以到达所有的点,算法正常结束
}
二 邻接矩阵 时间复杂度O(n^2)
#include <iostream>
#include <string.h>
using namespace std;
const int inf=0x3f3f3f3f;
int G[110][110];
int dist[110];
bool vst[110];
int n,m;
void dijkstra(int s){
memset(vst,false,sizeof(vst));
memset(dist,0x3f,sizeof(dist));
dist[s]=0;
for(int i=0;i<n;++i){
int v,min_d=inf;
for(int j=1;j<=n;j++){
if(!vst[j]&&dist[j]<min_d){
min_d=dist[j];
v=j;
}
}
vst[v]=true;
for(int j=1;j<=n;++j){
dist[j]=min(dist[j],dist[v]+G[v][j]);
}
}
}
int main() {
cin>>n>>m;
memset(G,0x3f,sizeof(G));
for(int i=0;i<m;++i){
int u,v,len;
cin>>u>>v>>len;
G[u][v]=G[v][u]=len;
}
dijkstra(1);
for(int i=1;i<=n;++i){
cout<<dist[i]<<" ";
}
return 0;
}
三、堆优化的Dijkstra 时间复杂度O((V+E)*lgV)
//小根堆优化的Dijkstra示例代码如下
const int MAX_N=10000;
const int MAX_M=100000;
const int inf=0x3f3f3f3f;
struct edge{
int v,w,next;
}e[MAX_M];
int p[MAX_N],eid,n;
void mapinit(){
memset(p,-1,sizeof(p));
eid=0;
}
void insert(int u,int v,int w){//插入带权有向边
e[eid].v=v;
e[eid].w=w;
e[eid].next=p[u];
p[u]=eid++;
}
void insert2(int u,int v,int w){//插入带权双向边
insert(u,v,w);
insert(v,u,w);
}
typedef pair<int,int>PII;
/*用set伪实现一个小根堆,并具有映射二叉堆的功能
堆中pair<int,int>的second表示顶点下标,
first表示该顶点的dist值*/
set<PII,less<PII> >min_heap;
int dst[MAX_N];//存储单源最短路的结果
bool vst[MAX_N];//标记每个顶点是否在集合U中
bool dijkstra(int s){
//初始化dist、小根堆和集合U
memset(vst,0,sizeof(vst));
memset(dist,0x3f,sizeof(dist));
min_heap.insert(make_pair(0,s));
dist[s]=0;
for(int i=0;i<n;++i){
if(min_heap.size()==0){//如果小根堆中没有可用顶点,说明有顶点无法从源点到达,算法结束
return false;
}
//获取堆顶元素,并将堆顶元素从堆中删除
auto iter=min_heap.begin();
int v=iter->second;
min_heap.erase(*it);
vst[v]=true;
//进行和普通dijkstra算法类似的松弛操作
for(int j=p[v];j+1;j=e[j].next){
int x=e[j].v;
if(!vst[x]&&dist[v]+e[j].w<dist[x]){
//先将对应的pair从堆中删除,再将更新后的pair插入堆
min_heap.erase(make_pair(dist[x],x));
dist[x]=dist[v]+e[j].w;
min_heap.insert(make_pair(dist[x],x));
}
}
}
} return true;//存储单源最短路的结果