单源最短路径算法

1.单源最短路径以及Dijsktra算法

2.多源最短路径以及Floyd算法


1.1单源最短路径:

即从一个特定的点出发,寻找这个点到其他点的最短路径

对于一个无权图,BFS算法就可以了。但是对于加权图,BFS行不通


1.2 Dijkstra(迪杰斯特拉):针对加权有向图、单源最短路径

dijkstra通过一个简单的动态规划思想来求最短路径。

(假设求从点s出的的单源最短路径)记D(w)为点s到点w的的最短路径,其状态转移方程:

D(w) = min{D(u)+w(u,w)};

u是还没有被访问过的,距离s距离最小的点。

顺次处理所有的点


伪代码:

for i:0->n-1

    do  

       v = minV(G,D)     //v是还没有被访问过的点中,离s距离最小的点

       set  V   visit

       for(w=G->first(v);w<G->n;w=G->next(v,w))                   //更新所有能通过v到达的点的距离

             do 

                 if D[w]>D[v]+w(v,w)

                  D[W] = D[v]+w(v,w)


2.多源最短路径以及Floyd算法

2.1多源最短路径:求任意两个点之间的最短路径


2.2Floyd算法  (相关:UVa576

插点+动态规划

d(i,j) = min{d(i,j),d(i,k)+d(k,j)}

即i,j两点之间的最短路径等于  i,j两点之间直接距离(如果i,j之间存在边的话)与i经过点k到j的距离中  最小的那一个


以下图为例


对应距离矩阵:


现在求两个点i,j两点经过点1时两点的最短路径,核心代码如下:

for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    if(e[i][j]>e[i][1]+e[1][j])
    e[i][j]=e[i][1]+e[1][j];

先求两个点i,j经过点1、2时两点的最短路径,核心代码如下

for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    if(e[i][j]>e[i][1]+e[1][j])
    e[i][j]=e[i][1]+e[1][j];

for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    if(e[i][j]>e[i][2]+e[2][j])
    e[i][j]=e[i][2]+e[2][j];

我们最终要求的是i,j经过点1,2。。。n时两点的最短路径,因此代码如下:

for(int k=1;k<=n;k++){
    for(int i=1;i=<n;i++)
      for(int j=1;j<=n;j++)
       if(e[i][j]>e[i][1]+e[1][j])
         e[i][j]=e[i][1]+e[1][j];
}

要注意,上述两种算法都不适用于权值有负数的图中

因为可能构成负权回路,而负权回路是没有最小路径的。

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页