题解 | #单源最短路#
单源最短路
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数组,这个也比较简单。