最短路径问题
Dijkstra算法:解决单源最短路径问题的贪心算法。
对于单源多节点 的最短路径问题,可以先使用Dijkstra算法求出长度最短的一条路径,再参照此路径求出长度次短的一条路径,直到求出源点到其他各个节点的最短路径
何为Dijkstra算法
将包括源点在内的所有节点V分为两组
- S:已确定最短路径的集合
- V-S:未确定最短路径的集合
新建一个变量来存储各个节点的最短路径
由于节点较多,使用dis[]数组来存储数据
对于节点t来说,通过S来寻找dis[t]的最小值,并在寻找结束后将节点t添加到集合S中,以用于对下一个节点的寻找。
如何使用Dijkstra算法
对于一个满足单源最短路径的问题
使用Dijkstra算法有以下几个步骤
- 确定数据结构:建立二维数组(邻接矩阵)来存储节点名称及距离,dis[]数组存储找到的最短路径,p[]数组记录最短路径上的最后一个节点
- 存入数据:源点u到自身的距离为0,所以初始时S中只有u,S={u},将dis[]数组中每个节点的数据先初始为其到u的距离,若不可直接到达源点则为∞,p[]数组若可以直接到达源点则初始为源点u,若不与源点直接相连则初始为-1
- 找最小距离:查找V-S中所有节点,找到距离源点最小距离的点将其加入S集合
- 松弛:因为上一步使得S中多了一个节点,对V-S中的所有节点检查是否可以借助S使得路径更短,如果可以则更新其对应的dis[],并将其记录进p[]
- 重复执行三四步直到V-S为空
例题
题目描述
为方便描述,直接给出如下邻接矩阵
∞ 2 5 ∞ ∞ ∞ ∞ 2 6 ∞ ∞ ∞ ∞ 7 1 ∞ ∞ 2 ∞ 4 ∞ ∞ ∞ ∞ ∞ 横向阅读其中第一排为源点u到各个节点的距离,以此类推
求源点u到各节点的最短距离
详解
按照刚刚给出的此类题的解决方式进行作答
-
数据结构:对于本题目来说,需要一个二维数组存放距离,dis[]存放最短距离,flag[]判断是否为集合S,p[]存放直接前驱
-
初始化:只对u进行操作,初始化u到其他各节点的距离
for (int i=0;i<5;i++){ dis[i]=G[u][i];//将dis初始化 flag[i]=false;//都还没找到最短距离 if(dis[i]==INF) p[i]=-1;//如果距离u的距离为无穷大则不相邻,不对p进行赋值 else p[i]=u; } flag[u]=true;//将源点划入集合S,要不然接下来无法执行 dis[u]=0;//源点到自身的距离为0
-
找最小
int tmp =INF,t=u for(int j = 1;j<5;j++)//重复执行 { if(!flag[j]&&dis[j]<tmp){//在集合V-S中和到源点距离比上一次循环小两个条件同时为假时,将这个数字记录下来以便将其加到集合S中且更新dis t =j; tmp =dis[j]; } if (t==u) return;//如果找不到节点t,则跳出循环。 flag[t]=ture; }
-
执行松弛操作
for(int j=1;j<n;j++){ if(!flag[j]&&dis[j]>dis[t]+G[t][j]){ dis[j]=dis[t]+g[t][j] p[j]=t; } }