最短路径问题

最短路径问题

14天阅读挑战赛

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为空

例题

题目描述

为方便描述,直接给出如下邻接矩阵

25
26
71
24

横向阅读其中第一排为源点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;
        }
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值