题解 | #单源最短路#

单源最短路

https://www.nowcoder.com/practice/9f15b34a2a944a7798a5340ff0dba8b7

class Solution {
public:
    int findShortestPath(int n, int m, vector<vector<int> >& graph) {
        // write code here
        /*单源最短路使用迪杰斯特拉算法。
        初始化时将S集中加入源点,并更新源点的邻接点的距离。
        往后扫描所有尚未加入S集的点,取距离最小者。每加入S集一个顶点,都要相应
        的尝试更新它的邻接点的值。(因为S集中新加入的顶点,只可能影响到它的邻接
        点的长度)*/
        if(graph.size()==0)
            return -1;
        //为每个顶点创建一个标志数组,记录其是否被加入到最短路中。
        vector<bool> flag(n);
        //表明现在每个节点距离节点1的最短距离。
        vector<int> dist(n);
        //对距离,flag数组进行初始化。距离都初始化为正无穷。
        for(int i=0;i<dist.size();i++)
        {
            dist[i]=INT_MAX;
            flag[i]=false;
        }
        //将源点加入进S集中。
        dist[0]=0;
        flag[0]=true;
        //将节点0的邻接点的距离初始化,同时考虑有重边的情况,重边时取最短边。
        for(auto edge:graph){
            if(edge[0]-1==0 && dist[edge[1]-1]>edge[2])
                dist[ edge[1]-1 ]=edge[2];
        }       
        
        while(1)
        {
            int mindistance=INT_MAX;
            int minIndex=-1;
            for(int i=0;i<dist.size();i++)
            {
                //在尚未加入S集的点中,寻找出一个距离最小的点来。
                if(dist[i]<=mindistance && flag[i]==false)
                {
                    minIndex=i;
                    mindistance=dist[i];
                }
            }
            //如果此时扫描出的结果发现剩余的点对S集来说是不可达的,就说明
            //这张图不是连通图,我们已经扫描完了这个连通分量了。
            if(mindistance==INT_MAX)
            {
                //判断目标点是否可达,或者说是否在该连通分量中。如果不在,返回-1
                if(dist[n-1]!=INT_MAX)
                    return dist[n-1];
                return -1;
            }

            //如果所有的点都加入到了S集中,就退出。
            if(minIndex==-1)
            {
                if(dist[n-1]!=INT_MAX)
                    return dist[n-1];
                return -1;
            }
            //遍历图,找出当前dist最小的节点的所有邻接边。
            for(auto edge:graph)
            {
                //由于在edge中记录的点是从1开始的,与数组中从0开始的差了1。所以要减一
                if( (edge[0]-1) == minIndex )
                {
                    //邻接点的下标。记得要减一
                    int adjoinIndex = edge[1]-1;
                    //如果将新点加入S集后,引起了该点的邻接点的最小距离变化,则更新
                    if(dist[adjoinIndex]>dist[minIndex]+edge[2])
                    {
                        dist[adjoinIndex]=dist[minIndex]+edge[2];
                    }
                }
            }
            flag[minIndex]=true;
        }
        return -1;
    }
};
多亏评论区有大佬提醒题目可能有重边……
另外如果要求输出路径的话还要加一个path数组,这个也比较简单。
全部评论

相关推荐

微风不断:兄弟,你把四旋翼都做出来了那个挺难的吧
点赞 评论 收藏
分享
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
11-21 17:16
科大讯飞 算法工程师 28.0k*14.0, 百分之三十是绩效,惯例只发0.9
点赞 评论 收藏
分享
1 收藏 评论
分享
牛客网
牛客企业服务