所有节点对之间的最短路问题(All Pair Shortest Path)--《算法导论》

原创 2016年08月28日 23:52:05

给定一个有向图求出里面所有节点对之间的最短路径。
问题的详细描述见Wikipedia:https://en.wikipedia.org/wiki/Shortest_path_problem
介绍两个算法O(V3)的Floyd算法和O(V2lgV+VE)的Jhonson算法。分别应对稠密图和稀疏图的情况。

Floyd

这是一个动态规划算法。设dkiji,j之间所有中间节点全部取自<1,2,...,i,...,k>的一条最短路的权重。则状态转移方程如下

dkij={wijmin{dk1ij,dk1ik+dk1ij}x=0x!=0

伪代码

for  k=1 to |V|
       for i=1 to V
              for j=1 to V
                     d[i][j]=min{d[i][j],d[i][k]+d[k][j]}

c++代码

void floyd(int n)
{
    memcpy(d,w,sizeof(w));//初始化d(0)
    for(int k=1 ; k<=n ; ++k)
        for(int i= 1 ; i<=n ; ++i)
            for(int j=1 ; j<=n ; ++j)
                d[i][j] = min(d[i][j],d[i][k]+d[k][j]);
}

Johnson(用于稀疏图)

Johnson算法的核心思想是直接对每个顶点做一次Dijkstra,这样时间复杂度只有O(VElgV)(用斐波那契堆实现只需O(V2lgV))对于稀疏图来说是会渐进优于Floyd算法的,但是我们知道Dijkstra算法只能用于权重为正数的情况。所以要对图上的权重进行重新映射一次。

重塑权重值
p:<v0,...,vi,...,vk>为从v0vk的一条最短路,则重塑的权重w必须满足两个条件:

1、w(p)=δ(v0,vk)w(p)=δ(v0,vk)
2、w(p)不包含负环 w(p)不包含负环

下面证明取权重映射w(u,v)=w(u,v)+h(u)h(v)时满足条件。

w(p)=ni=1w(vi,vi1)

         =ni=1w(vi,vi1)+h(v0)h(vk)

         =w(p)+h(v0)h(vk)

第一条肯定满足了,因为h(v0),h(vk)是预处理出来的常数,第二条,当p为一负权重的环路时,v0=vk,所以w(p)=w(p)也是负环。

构造函数h

我们采取的方法是这样的,添加一新节点编号为0,到每一个顶点的距离为0,然后我们令h(v)=δ(0,v),由三角不等式h(v)h(u)+w(u,v),所以w(u,v)0

简单写一下伪代码
伪代码

compute G

spfa(G’,0)

foreach vertex v G.V

        h(v=δ(0,v)

foreach edge (u,v)G.E

        w(u,v)=w(u,v)+h(u)h(v)

foreach vertex v G.V

Dijkstra(G,v)

for i=1 to V

       forj=1 to V

           d[i][j]=d[i][j]+h[j]h[i]

c++代码

void spfa(int s)
{
    for(int i=1 ; i<=nv ; ++i)d[s][i] = INF;
    d[s][s] = 0;
    memset(inq,false,sizeof(inq));
    queue<int> q;
    q.push(s);
    inq[s] = true;
    while(!q.empty())
    {
        int u =q.front(); q.pop();
        inq[u] = false;
        for(int i=first[u] ; i!=-1 ; i = nt[i])
        {
            Edge &e = edges[i];
            if(d[s][e.to]>d[s][u]+e.weight)
            {
                d[s][e.to]=d[s][u]+e.weight;
                if(!inq[e.to]){
                    q.push(e.to);inq[e.to] = true;
                }
            }
        }
    }
}
void dijkstra(int s)
{
   bool vis[MAX_V];
   memset(vis,false,sizeof(vis)); 
    for(int i=1 ; i<=nv ; ++i)d[s][i] = INF;
    d[s][s] = 0;

    priority_queue<pii,vector<pii>,greater<pii> > q;
    q.push(pii(0,s));

    while(!q.empty())
    {
        int u = q.top().second;q.pop();
        if(vis[u])continue;
        else vis[u] = true;
        for( int i=first[u] ; i!=-1 ; i = nt[i])
        {
            Edge& e = edges[i];
            if(d[s][e.to]>d[s][u]+e.weight)
            {
                q.push(pii(d[s][e.to],e.to));
                d[s][e.to] = d[s][u]+e.weight ;
            }
        }
    }
}
void compute_Go(int last_edge)//最后一条边编号
{
    int id = last_edge+1;
    for(int i=1 ; i<=nv ;++i )
    {
        read_edge(0,i,0,id);//向边集数组添加新边
        id++;
    }
}
void johnson()
{
    int h[MAX_V];
    compute_Go(ne);
    spfa(0);
    for(int i=1 ; i<=nv ;++i)h[i] = d[0][i];
    //重塑边权重
    for(int i=1 ; i<=ne ;++i)
    {
        Edge &e = edges[i];
        e.weight = e.weight+h[e.from]-h[e.to];
    }
    for(int i=1 ; i<=nv ; ++i)
    {
        dijkstra(i);
    }
    //映射回原来的最短路径
    for(int i=1 ;i<=nv  ;++i)
    {
        for(int j=1 ; j<=nv ; ++j)
            d[i][j] = d[i][j]+h[j]-h[i];
    }
}

Johnson算法实现太复杂,在V不是很大的时候都建议用floyd。
代码测试题poj 1125。。。。就是water problem了。。。

版权声明:本文为博主原创文章,未经博主允许不得转载。

算法导论笔记:25所有节点对的最短路径问题

本章考虑在给定的有向加权图G=(V, E),对于所有的节点u,v∈V,找到一条从节点u到节点v的最短路径。希望以表格的形式表示输出:第u行第v列给出的是节点u到节点v的最短路径权重。        对...
  • gqtcgq
  • gqtcgq
  • 2015年05月10日 16:02
  • 2661

所有节点对的最短路径问题

前面在《单源最短路径》中我们接触了最短路径问题,并介绍了求解最短路径问题的算法,比如Bellman-Ford算法,Dijkstra算法。不过,那里我们计算的是从一个固定的源节点到所有其他点的最短路径。...
  • cumtwyc
  • cumtwyc
  • 2015年01月15日 19:37
  • 1983

【算法导论】【Floyd-Warshall 算法】每对节点之间的最短路径

所有结点对的最短路径问题 目录 所有结点对的最短路径问题 计算最短路径权重 - Floyd 算法 邻接矩阵 最短路径的结构 所有结点对最短路径问题的一个递归解 自底向上计算最短路径权重 打...
  • ideaqjx
  • ideaqjx
  • 2017年12月23日 17:15
  • 210

算法导论笔记:25所有节点对的最短路径问题

本章考虑在给定的有向加权图G=(V, E),对于所有的节点u,v∈V,找到一条从节点u到节点v的最短路径。希望以表格的形式表示输出:第u行第v列给出的是节点u到节点v的最短路径权重。        对...
  • gqtcgq
  • gqtcgq
  • 2015年05月10日 16:02
  • 2661

最短路径算法(Shortest-path Algorithms)

0) 引论 正如名字所言,最短路径算法就是为了找到一个图中,某一个点到其他点的最短路径或者是距离。 最短路径算法一般分为四种情况: a) 无权重的最短路径 b) 有权重的最短路径 c) 边的权重为负的...
  • changyuanchn
  • changyuanchn
  • 2013年12月03日 11:43
  • 7801

第25章:所有结点对的最短路径问题—floyd-warshall和Johnson算法

二:Floyd-Warshall算法\quad该算法适用于边权重可以为负值,但环路权重和不能为负值的图,其运行时间为Θ(V3)\Theta(V^{3})。\quad假设dkijd_{ij}^{k}为从...
  • weishenmetlc
  • weishenmetlc
  • 2016年07月15日 19:14
  • 1115

单源最短路径(Single Source Shortest Path)--《算法导论》

关于最短路径的描述请参考维基百科Shortest Path简单总结一下算法导论上描述的计算从单一节点源到图中每一节点的最短路径算法,Bellman-Ford算法及其优化版本spfa,以及对权重非负的图...
  • Dylan_Frank
  • Dylan_Frank
  • 2016年08月28日 21:12
  • 500

【算法导论】【Floyd-Warshall 算法】每对节点之间的最短路径

所有结点对的最短路径问题 目录 所有结点对的最短路径问题 计算最短路径权重 - Floyd 算法 邻接矩阵 最短路径的结构 所有结点对最短路径问题的一个递归解 自底向上计算最短路径权重 打...
  • ideaqjx
  • ideaqjx
  • 2017年12月23日 17:15
  • 210

算法导论 第二十五章 所有节点对的最短路径问题

基于单源最短路径问题的讨论,解决所有最短路径问题,对每个节点求其最短路径: 25.1 最短路径和矩阵乘法...
  • pokeyode
  • pokeyode
  • 2017年04月25日 17:32
  • 280

算法导论笔记:25所有节点对的最短路径问题

本章考虑在给定的有向加权图G=(V, E),对于所有的节点u,v∈V,找到一条从节点u到节点v的最短路径。希望以表格的形式表示输出:第u行第v列给出的是节点u到节点v的最短路径权重。        对...
  • gqtcgq
  • gqtcgq
  • 2015年05月10日 16:02
  • 2661
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:所有节点对之间的最短路问题(All Pair Shortest Path)--《算法导论》
举报原因:
原因补充:

(最多只允许输入30个字)