迪杰斯特拉做题步骤

1、问题分析:迪杰斯特拉算法是解决最短路径问题(即:两点之间的距离)

它于最小生成树的区别:

最小生成树针对所有的点而言的算法,最小生成树的所有点的边权值加起来值最小,但是两个点距离 ( 权值 ) 不一定是最小的。

迪杰斯特拉算法针对的是两个点之间的距离最短。

这道题的做题步骤是以 紧急救援 为例 而做的总结:

2、先输入题目给的信息:城市个数,城市的通道数,起点,终点,用一个数组(city)来保存每个城市的救援队的数量。

3、构建结构体,包含 v(通道能到达的城市) ,w (边权值),这里需要写重载函数(把 < 重载为 > , 原因就是优先队列默认是大根堆,我们需要将运算符重载,这样就变成小根堆了)。

4、使用邻接表构建图邻接表是动态二维数组( vector < node > a[ N ] ), a [ i ] 里面保存的是 i 城市分别可以到达的城市。

5、直接调用 dijkstra 函数:

(1)建立优先队列( priority_queue < node > q ),并将起点城市入队( q . push ( { s , 0 } ) )

(2)创建初始化数组,需要一个记录到某个点的最小权值数组dis数组,初始化为 0x3f3f3f3f )和记录答案路径的数组( pre数组初始化为 -1 ).,还有记录救援队人数总和的数组(起点位置的救援总数为自己城市的救援数量),创建vis数组记录每个结点的为起点的情况,防止重复访问

(3)当队列不为空候,取出队首并将队首pop()(优先队列的队首为 top ( ) ),将队首中的城市取出,判断这个城市有没有访问过访问过就 continue 没访问过就将这个城市标记访问过。

(4)循环遍历 ( i ) 从这个城市能到达的城市(a [ t ] . size ( )  ),j = a [ t ][ i ] . y 表示的是(从 t 这个城市到城市 y , i 是下标) ,a [ t ][ i ] . w 表示的是(从 t 这个城市到城市 y 需要的边权值, i 是下标)

(5)判断能否做松弛操作(即 if ( dis [ j ] > dis [ t ] + w ) ),

        如果可以松弛操作,就更新dis [ j ] 的值( dis [ j ] = dis [ t ] + w),就将 j 这个城市和 j 这个城市对应的最小权值( w )dis [ j ] 入队

        for(int i=0,l=a[t].size(); i<l; i++) {
            int j=a[t][i].y,w=a[t][i].w;//j 是当前城市到达下一个城市的城市号码,w 是当前城市到达下一个城市的长度
            if(dis[j]>dis[t]+w) {//松弛操作
                dis[j]=dis[t]+w;
                q.push({j,dis[j]});
                sum[j]=sum[t]+city[j];
                cnt[j]=cnt[t];
                pre[j]=t;//记录上一个位置
            } else if(dis[j]==dis[t]+w) {//如果路径长度相同,更新救援最大数量
                cnt[j]+=cnt[t];
                if(sum[j]<sum[t]+city[j]) {
                    sum[j]=sum[t]+city[j];
                    pre[j]=t;//更新当前结点的上一个位置
                }
            }
        }

(6)写一个 print 函数将答案输出,可以定义一个栈 stack < int > S,将记录的路径输入栈里面,然后倒着输出,注意判断行末不能有空格

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值