Dijkstra算法
适用于边权为正的情况下,有向图与无向图均适用
用途:
计算正权图上的单源最短路(Single-Source Shortest Paths,SSSP)
步骤:
1>. 初使时令 S={V0},T={其余顶点},T中顶点对应的距离值,若存在<V0,Vi>,为<V0,Vi>弧上的权值(和SPFA初始化方式不同),若不存在<V0,Vi>,为Inf。
2>. 从T中选取一个其距离值为最小的顶点W(贪心体现在此处),加入S(注意不是直接从S集合中选取,理解这个对于理解vis数组的作用至关重要),对T中顶点的距离值进行修改:若加进W作中间顶点,从V0到Vi的距离值比不加W的路径要短,则修改此距离上面两个并列for循环,使用最小点更新)。
伪代码:
(1)清除所有点的标号
(2)设d[0]=0,其他d[i]=INF
(3)循环n次
{
在所有未标号的节点中,选出d值最小的节点x
给结点x标记
对于从x出发的所有边(x,y),更新d[y]=min{ d[y],d[x]+w(x,y) }
}
//假设起点是结点0,它到结点i的路径长度为d[i],未标号的结点的v[i]=0,已标号的结点的v[i]=1.用w[x][y]==INF表示边(x,y)不存在
//Dijkstra算法
memset(v, 0, sizeof(v));
for(int i = 0; i < n; i++)
d[i] = (i == 0 ? 0 :INF);
for(int i = 0; i < n; i++)
{
int x,m =INF;
for (int y = 0; y < n; y++)
if(!v[y] && d[y]<=m) m = d[x=y];
v[x]=1;
for(int y = 0; y < n; y++)
d[y] = min(d[y], d[x] + w[x][y]);
}
松弛操作:(relaxation)
松弛操作就是让顶点与顶点之间的路径变短的操作,就像一根橡皮筋连接x和y两点,现在有一点v到y的路径更短,现在把橡皮筋y点的另一端x换成v点,这样缓解橡皮筋紧绷的压力,让其变得松弛。
下面的代码是边(x,y)上的松弛操作
//松弛操作
if (d[y] > d[x] +w[x][y])
{
d[y] = d[x] + w[x][y];
fa[y] = x;
}
时间复杂度:O(n^2)
解析: 循环体一共执行了n次,在每次循环中“求最小d值”与“更新其他d值”的时间复杂度均为O(n)
算法优化:
该算法可以采用邻接表的方法将算法时间复杂度变为O(mlogn)
其中最坏的情况是m与n^2同阶,此时算法为负优化。
m与n^2有以下两种关系:
(1)m远小于n^2 称为稀疏图(Sparse Graph) 适合使用vector数组保存。
(2)m大于n^2 称为稠密图(Dense Graph) 适合使用邻接表(Adjacency List)保存。