Dijkstra算法核心思想:
求起始点到达某一点的最短距离,所有点被分为两个集合,已确定最短路径长度的顶点集合S和未知最短距离顶点集合V-S。用dist[j]表示点j到达起始点的最短距离,借助中间点t,可能起始点与点j的直接距离大于借助中间点t的间接距离,此处需要加以判断,同时需要更新dist[j];此外需要借助pre[max]数组存中间点t,方便寻找最短路径具体过程。
核心步骤:初始化—>寻找距离中间点t的最短距离—>将距离最短的点t加入集合S—>更新最短距离—>记录中间点t的路径存在pre[max]
动画效果演示:Dijkstra算法
算法具体实现:
#include <bits/stdc++.h>
using namespace std;
const int maxx=1e3; //点的数量的最大取值
const int inf=0x3f3f3f3f;
int mp[maxx][maxx]; //记录每条边的权值信息
int flag[maxx]; //标记该点是否加入集合S中
int dist[maxx]; //表示该点与起始点的最短距离
int pre[maxx]; //记录该点的前驱结点,从而记录最短路径过程
int n,m,u,v,w;
void Dijkstra(int u){ //设起始点为u
for(int i=1;i<=n;i++){ //进行初始化
dist[i]=mp[u][i]; //初始状态设各个点到达起始点的最短距离为mp[u][i]
flag[i]=0; //初始状态未选择任何点,集合S为空集
if(dist[i]==inf) //点i与起始点没有直接路径
pre[i]=-1;
else
pre[i]=u; //点i与起始点直接相连,则点i的前驱结点为起始点u
}
dist[u]=0; //点u到达起始点u自身距离为0
flag[u]=1; //将起始点u加入集合S
for(int i=1;i<=n;i++){
int temp=inf,t=u; //temp为中间变量,用于寻找最短距离dist[j];t是连接起始点u到达点j的中间点
for(int j=1;j<=n;j++){
if(!flag[j]&&dist[j]<temp){
temp=dist[j]; //找到最短距离
t=j; //记录中间结点t
}
}
if(t==u) return; //找不到t直接退出
flag[t]=1; //将中间点t加入集合S
for(int j=1;j<=n;j++){ //更新点j到达起始点的最短距离
if(!flag[j]&&mp[t][j]<inf){
if(dist[j]>dist[t]+mp[t][j]){
dist[j]=dist[t]+mp[t][j];
pre[j]=t; //将点t存入pre数组
}
}
}
}
}
//用于返回起始点到达某个点i的路径过程
void findpath(int u){
int x;
stack<int>s; //返回中间点t的过程是逆过程,采用栈进行存储
for(int i=1;i<=n;i++){
x=pre[i]; //设x为u->i路径中点i的前驱结点
while(x!=-1){
s.push(x); //将前驱结点x依次压入栈中
x=pre[x];
}
while(!s.empty()){ //若栈非空,则依次弹出栈内的中间点
cout<<s.top()<<"->"; //获取栈顶元素,此时栈顶元素未被删除
s.pop(); //删除栈顶元素
}
cout<<i<<";最短距离为:"<<dist[i]<<endl; //最后输出终点i,以及u->i的最短距离
}
}
int main()
{
int u,v,w,st;
cin>>n>>m;
memset(mp,inf,sizeof(mp)); //初始化数组边的权值
memset(dist,inf,sizeof(dist)); //初始化各个点到达起始点的最短路径
for(int i=1;i<=m;i++){
cin>>u>>v>>w; //依次输入边的权值信息
mp[u][v]=min(mp[u][v],w);
}
cin>>st; //输入起始点
Dijkstra(st); //获得st->j路径的最短距离
findpath(st); //返回该路径全过程
return 0;
}
样例测试
输入:
城市个数n,道路数量m
5 11
请输入城市之间的路线以及距离
1 5 2
5 1 8
1 2 16
2 1 29
5 2 32
2 4 13
4 2 27
1 3 15
3 1 21
3 4 7
4 3 19
输入起始位置st:
5
输出:
5->1;最短距离为:8
5->1->2;最短距离为:24
5->1->3;最短距离为:23
5->1->3->4;最短距离为:30
5;最短距离为:0
希望对你有所帮助!