[图算法]多段图最短路径

Posted kasperskynod

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[图算法]多段图最短路径相关的知识,希望对你有一定的参考价值。

[图算法]多段图最短路径

多段图最短路径问题是应用动态规划的经典问题之一,许多优化问题都能转化为多段图最短路径问题进而求解。多段图最短路径的问题描述如下:

问题描述

设G=(V,E)是一个赋权有向图,其顶点集V被划分为k个不相交的子集Vi(1<=i<=k),其中,V1和Vk分别只有一个顶点s(称为源)和一个顶点t(称为汇),所有的边(u,v)的始点和终点都在相邻的两个子集Vi和Vi+1中, 且边(u,v)有一个正权重,记为w(u,v).请设计一个算法,求解从源s到汇t的权重之和最小的路径。

问题分析

此问题具有最优子结构性质:假如1–2–7–10–12为上图中源节点1到汇节点12的一条最短路径,那么1–2–7–10一定为节点1到节点10的最短路径(反证法可以证明)。所以此问题适用于动态规划算法。

设w(i,p)为源节点s到节点v(i,p)的最短路径代价(i指阶段序号,p指第i阶段中的节点序号),而节点v(i+1,q)为节点v(i,p)的一个后继节点(所谓后继节点,即v(i+1,q)为v(i,p)下一阶段的一个节点,且v(i,p)到v(i+1,q)之间有一条路径。因为v(i,p)的后继节点可能有多个,所以设v(i+1,q)为“其中一个”后继节点。同理,称节点v(i,p)为节点v(i+1,q)的一个前驱结点)。则从源节点经由节点v(i,p)到节点v(i+1,q)的路径代价为w(i,p)+w(p,q)。当遍历v(i+1,q)的所有前驱节点后,会计算出一个最小的代价值,把它作为w(i+1,q)的值。把上述逻辑用数学递推式来表示为:

问题求解

采用自底向上的动态规划算法进行求解,先求解源s到第2阶段所有节点的最短路径,然后求第3阶段所有节点的最短路径,以此类推,直到求到汇节点t,即为我们所要求的值。程序中,我们采用一张表格(二维数组)来存储各个节点到源节点s的最短路径值。这样,我们能求出最短路径的值,如果还需要求具体的路径,则还需要维护一张表格,记录路径中的节点号。

以下程序摘自互联网资源 http://blog.csdn.net/u012432778/article/details/41623961 ,我没有亲自验证,不保证完全正确。

#include <stdio.h>
#include <stdlib.h>

#define MaxState 100

int minRoad[MaxState][MaxState];
void multiStageGraph(int stageNum, int *numPerStage);

int main()

    int i, k, ni[MaxState];
    while(scanf("%d", &k),k != -1)
    
        for(i = 0; i < k; ++i)
        
            scanf("%d", &ni[i]);
        
        multiStageGraph(k, ni);
    
    return 0;


void multiStageGraph(int stageNum, int *numPerStage)

    int i, q, p, weight, temp;
    memset(minRoad, 0x3f, sizeof(minRoad));           //初始化为一个充分大的数0x3f

    for (p = 0; p < numPerStage[0]; ++p)              //初始化源顶点层
    
        minRoad[0][p] = 0;
    

    for (i = 0; i < stageNum - 1; ++i)                //按段计算,终止与汇顶点的前一段
    
        for (q = 0; q < numPerStage[i]; ++q)          //遍历第i段顶点
        
            for (p = 0; p < numPerStage[i + 1]; ++p)  //遍历第i+1段顶点
            
                scanf("%d", &weight);                 //读取边(q,p)的权重w(q,p)
                if (weight != -1)                     //存在边(q,p)
                
                    temp = minRoad[i][q] + weight;
                    if (temp < minRoad[i+1][p])       //发现s到o的更短路径
                    
                        minRoad[i+1][p] = temp;
                    
                
            
        
    
    printf("%d\\n", minRoad[stageNum-1][0]);


参考资料:
[1] http://blog.csdn.net/u012432778/article/details/41623961
[2] 算法导论第六部分:图算法

以上是关于[图算法]多段图最短路径的主要内容,如果未能解决你的问题,请参考以下文章

多段图动态规划dp

算法 动态规划

数据结构与算法图最短路径算法 ( Floyed 算法 | 图最短路径算法使用场景 | 求解图中任意两个点之间的最短路径 | 邻接矩阵存储图数据 | 弗洛伊德算法总结 )

无向图最短路径算法

教你一招 | Python实现无向图最短路径

搜索带权图最短路径的Dijkstra算法