学习图论(四)——单源最短路问题

一年前写的最短路的博客写得太一般了,代码也很难看,刚好最近复习到相关知识,所以重新整理一下

下面涉及题目的代码都在力扣上通过。

 

一、DFS

 DFS可以用来求给定两点之间的最短路。即走遍两点间的所有路径,选择路程最小的那一个

我们可以从U出发,记录已经走过的路程。

采用邻接矩阵的方式来表示图:graph[u][v]=w表示u到v之间有一条权重为w的边,若u和v之间无边,则令graph[u][v]=0。

为了防止两点之间有回路导致DFS时一直在回路上绕圈子,我们定义vis数组来记录当前已经访问过的节点,已经访问过的节点不再访问。(回溯的思想)

设一个全局变量MinDistance表示要求的最短路程。

   void dfs(vector<vector<int>>& graph,vector<bool>& vis,int src,int dest,int distance){
        if(src==dest){
            //此时得到了起点到终点之间的一条路径,路程为distance
            //假设起点和终点之间的最短路为MinDistance,则执行 MinDistance=min(MinDistance,distance)
        }
        else{
            vis[src]=true;
            for(int next_node=1;next_node<graph.size();++next_node){
                if(graph[src][next_node]==0) continue;
                int cur_distance=distance+graph[node][next_node];
                if(vis[next_node]==false && cur_distance<MinDistance) dfs(graph,vis,next_node,dest,cur_distance);
            }
            vis[node]=false;
        }
    }

 上面的代码做了优化,因为我们要求的是最短路,那么如果当前走过的路程已经超过了最短的路程,那么没必要再走下去了。


二、迪杰斯特拉算法

迪杰斯特拉算法用于求单源最短路程问题,即假设图中有N个顶点,其中一个顶点为U,那么我们可以用迪杰斯特拉算法求得顶点U与其他N-1个顶点之前的最短路程。

算法原理:在还未被访问的顶点中选择离U最近的顶点MID,以MID作为中介点,更新U通过MID到达与MID相邻的顶点的最短路程。

这里的更新被称为松弛操作。我们通过MID点更新U到V的最短路程,需要:

if(U到V的最短路 > U到MID的最短路+MID到V的距离)
    U到V的最短路 = U到MID的最短路+MID到V的距离

可以发现每次我们选择一个MID,一共有N个节点,除去U不参与选择,则我们要做N-1次相同的操作,每次取出不同的MID。

Leetcode上有对应的题目:743. 网络延迟时间

下面给出该题的题解,使用了迪杰斯特拉算法,核心就是求单源最短路程。如果不想看题目也可以直接看下面的迪杰斯特拉算法的实现。

class Solution {
public:
    int networkDelayTime(vector<vector<int>>& times, int N, int K) {
        vector<vector<int>> graph(N+1,vector<int>(N+1,101));
        for(auto edge:times){
            int from=edge[0],to=edge[1],time=edge[2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值