Dijkstra算法:用来解决单源最短路问题,就是给出一个图的起点,通过算法可以得到这个点到达其他所有点的最短距离。
接下来简单讲一下Dijkstra算法:
假设现在有6个城市(v0~v5),现在要用Dijkstra算法求出由V0到其他城市的最短路径。
下面讲一下步骤:(假设现在所有城市都关闭了,城市之间的路都被遮住了,只有开放这个城市之后,该城市到其他城市的路才会开放)(用蓝色代表关闭城市,橙色代表开放城市)
(1)每次都从没有开放的城市中选择距离V0最近的城市,前往开放。
(2)开放Vk之后,开放从他出发的所有道路,并查看,在以Vk为中介点的情况下,能不能让从V0到达某些还没有开放的城市的最短距离变小。如果能,则将那个最短距离覆盖到对应的城市上。
(每个城市到自己的距离都是0,在城市未开放时到其他城市的距离都为INF(非常大))
1)当前还没有开放的城市是{v0,v1,v2,v3,v4,v5},从v0出发,距离最短的是他自己(v0-V0距离为0,到其他所有城市距离为INF),所以开放V0,这样(V0-V1,V0-V4,V0-V3的路就都开放了)(V0-V1最短距离为1,V0-V3最短距离为4,V0-V4最短距离为4)
2)从{V1,V2,V3,V4,V5}中选最短距离,可以看出是V1,因此开放V1。此时V0-V3的最短距离就从4变成了3(现在V0-V1最短距离为1,V0-V3最短距离为3,V0-V4最短距离为4)
3)从{V2,V3,V4,V5}中选最短距离,可以看出是V3,开放V3。(现在V0-V1最短距离为1,V0-V2最短距离为5,V0-V3最短距离为3,V0-V4最短距离为4)
4){V2,V4,V5}中选最短路,选V4.(现在V0-V1最短距离为1,V0-V2最短距离为5,V0-V3最短距离为3,V0-V4最短距离为4,V0-V5最短路径为7)
5)开放V2,最后开放V5。因此V0-V5的最短距离变为6.
最后得到的结果就是(V0-V1最短距离为1,V0-V2最短距离为5,V0-V3最短距离为3,V0-V4最短距离为4,V0-V5最短路径为6)
下面给一道与该算法有关的题
7-9 旅游规划 (25分)
有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。
输入格式:
输入说明:输入数据的第1行给出4个正整数N、M、S、D,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0~(N−1);M是高速公路的条数;S是出发地的城市编号;D是目的地的城市编号。随后的M行中,每行给出一条高速公路的信息,分别是:城市1、城市2、高速公路长度、收费额,中间用空格分开,数字均为整数且不超过500。输入保证解的存在。
输出格式:
在一行里输出路径的长度和收费总额,数字间以空格分隔,输出结尾不能有多余空格。
输入样例:
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20
输出样例:
3 40
题中做成图就是这样,d代表路长度,cost代表收费
代码实现(C++)
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxv=505;
const int inf=10000000;
//n为顶点数,m为边数,st为起点 ,ed为终点,G[][]为距离矩阵,cost为花费矩阵
int n,m,st,ed,G[maxv][maxv],cost[maxv][maxv];
//d记录最短距离,c记录最小花费
int d[maxv],c[maxv];
bool vis[maxv]={false};//标记数组,vis[i]=true表示已访问
void dijk(int s)//起点s
{
fill(d,d+maxv,inf);//fill函数将整个d数组赋为inf
fill(c,c+maxv,inf);
d[s]=0;//起点s到自身的距离为0;
c[s]=0;
for(int i=0;i<n;i++)
{
int u=-1,min=inf;//u使d[u]最小,min存放该最小的d[u];
for(int j=0;j<n;j++)
{
if(vis[j]==false&&d[j]<min)
{
u=j;
min=d[j];
}
}
if(u==-1) return ;//找不到小于inf 的d[u],说明剩下的顶点和起点s不连通
vis[u]=true;
for(int v=0;v<n;v++)
{
if(vis[v]==false&&G[u][v]!=inf)//如果v未访问&&u能到达v
{
if(d[u]+G[u][v]<d[v])
{
d[v]=d[u]+G[u][v];//优化d[v];
c[v]=c[u]+cost[u][v];//优化c[v];
}
else if(d[u]+G[u][v]==d[v])//如果路径长度相等
{
if(c[u]+cost[u][v]<c[v])
{
c[v]=c[u]+cost[u][v];
}
}
}
}
}
}
int main()
{
cin>>n>>m>>st>>ed;
int u,v;
fill(G[0],G[0]+maxv*maxv,inf);//初始化图
for(int i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
scanf("%d%d",&G[u][v],&cost[u][v]);
G[v][u]=G[u][v];
cost[v][u]=cost[u][v];
}
dijk(st);
cout<<d[ed]<<' '<<c[ed];
}