dijkstra算法求单源最短路径
我引用了这位大佬的文章:
https://blog.csdn.net/xiaoxi_hahaha/article/details/110257368
但是他的文章代码有一些问题, 我进行了一些修改, 特此进行记录
先贴出原作者源代码:
原作者把每一行的注释都写得很清楚,很感谢
const int inf = 500; //可以给别的值,只要大于图中任何一边的距离即可
vector<int> dijkstra(vector<vector<int> > G,int source)
{
int n = G.size(); //n代表图的顶点个数
vector<int> dis(n,inf); //dis代表源点到其它点的最短距离,inf代表无穷,初始化vector
vector<int> vis(n,false); //vis代表某个顶点是否被访问过,初始化所有的顶点为false
//源点到源点的距离为0
dis[source]=0;
/*
根据前面咱们的分析可以知道,要不断寻找没有被访问过且距离源点最近的点,有n个顶点,
就要寻找n-1次,找到点之后,对其邻接点进行松弛,为什么只要寻找n-1个点呢?因为当
剩下一个点的时候,这个点已经没有需要松弛的邻接点了。此时从源点到这个点的距离就是最短距离了。
*/
//可以使用一个for循环,循环n-1次,来寻找n-1个点
for(int i=0; i<n-1; i++)
{
int node = -1; //进入循环之后,假设一开始不知道哪个是没有被访问过且距离源点最短的点
for(int j=0;j<n;j++) //使用这个循环开始寻找没有被访问过且距离源点最短距离的点
{
if(!vis[j] && (node == -1 || dis[j]<dis[node]))
{
node = j; //把当前距离源点最短距离的点给node
}
}
//对这个距离源点最短距离的点的所有邻接点进行松弛
for(int j=0; j<n; j++)
{
dis[j]=min(dis[j],dis[node]+G[node][j]);
/*
这边要特别注意:对于不是node的邻接点并不会影响它原来的距离,以2点为例
对于邻接的已经访问过的点也不会产生影响,以3点为例
*/
}
//标记为已访问过
vis[true];
}
return dis;
}
我觉得错误点就在于第一个for循环, 并不符合dijsktra算法的要求, 原作者用用节点0到5进行遍历,这不是dijsktra的算法要求, 这里的循环条件应该改为:当ins序列中并不是所有的点都被标记过, 则循环继续, 而且source源点变量也没有发挥它应有的价值,我改进的代码如下:
int sum(vector<int> a) //用来计算是否每一个点都被标记过, 如果sum值为7说明全部被标记过
{
int s = 0;
for(vector<int>::iterator iter = a.begin();iter != a.end();iter++)
s += *iter;
return s;
}
vector<int> dijkstra(vector<vector<int>> G,int source)
{
const int inf = 1e8;
int n = G.size();
vector<int> road(n,inf);
vector<int> ins(n,0);
road[source] = 0;
ins[source] = 1;
while(sum(ins)!=7)
{
for(int i=0;i<n;i++)
road[i] = min(road[i],road[source]+G[source][i]);
int node = -1;
for(int i=0;i<n;i++)
if(!ins[i] && (node==-1 ||road[i]<road[node]))
node = i;
source = node;
ins[source] = 1;
}
return road;
}
最后贴上相应的源程序方便大家直接运行看结果:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int inf = 1e8;
int sum(vector<int> a) //用来计算是否每一个点都被标记过, 如果sum值为7说明全部被标记过
{
int s = 0;
for(vector<int>::iterator iter = a.begin();iter != a.end();iter++)
s += *iter;
return s;
}
vector<int> dijkstra(vector<vector<int>> G,int source)
{
// const int inf = 1e8;
int n = G.size();
vector<int> road(n,inf);
vector<int> ins(n,0);
road[source] = 0;
ins[source] = 1;
while(sum(ins)!=7)
{
for(int i=0;i<n;i++)
road[i] = min(road[i],road[source]+G[source][i]);
int node = -1;
for(int i=0;i<n;i++)
if(!ins[i] && (node==-1 ||road[i]<road[node]))
node = i;
source = node;
ins[source] = 1;
}
return road;
}
int main()
{
vector<vector<int>> G = {{0,5,2,inf,inf,inf,inf},{5,0,inf,1,6,inf,inf},{2,inf,0,6,inf,8,inf},{inf,1,6,0,1,2,inf},{inf,6,inf,1,0,inf,7},{inf,inf,8,2,inf,0,3},{inf,inf,inf,inf,7,3,0}};
vector<int> a = dijkstra(G, 0);
for(int i=0;i<G.size();i++)
cout<<a[i]<<endl;
}