• 【总结】最短路径条数问题


    例题:NOI2007 社交网络【难度不大,主要就是考察了这个知识点】

    本文进过原作者同意转载,原博主为:  erosun

    原地址:http://www.cnblogs.com/acxblog/p/7592158.html

    Problem:给定一张n个点m条边的带权有向图,从起点s出发到达终点e,有多少种方法可以走最短的路径到达终点e?

    Solution:

    首先我们得找到s到各点的单源最短路值(SPFA/Dijkstra)。

    问题一,如何确定某个点k是否在s到v的最短路上。这只需要一个判断语句:dist[s][k]+dist[k][v]==dist[s][v]。

    问题二,如何从v点出发走最短路径走到点s?找边集(v,k)使得dist[s][k]+edge[k][v]==dist[s][v]。到达点k后,我们再沿k到s的最短路走即可。为什么不是dist[s][k]+dist[k][v]==dist[s][v]?因为若是dist[k][v],k到v的最短路径上可能并非单边,而是多条边和多个点。

    知道这些后,我们可以使用搜索遍历每条s到v的最短路(从v出发),然后统计路径的条数加起来。然而这个路径数可能很大,这样子的话就会超时。

    那么我们不妨使用记忆化搜索。这样的话这个问题转换成了一个dp方程。
    状态:f[i][j] 从i到j的最短路条数值
    转移:f[i][j]=sum{f[i][k]} ( (k,j)属于E , d[i][k]+e[k][j]==d[i][j] )
    边界:f[i][i]=1

    问题得到解决。

    然而这玩意会不会有更好的解决方法?到底究竟要不要使用递归?有,可以不用递归。

    当我们跑了一边SPFA之后,以s为源,整张图会转换成一个最短路图。点u能向点v连一条有向边的条件为dist[u]+e[u][v]==dist[v]。整张图应该转成了一张DAG(边权为正)。

    那么s到一个点k的最短路,也就是f[k],应该从sum{f[j]} ( (j,k)属于E )转换过来,也就是每个出边指向k的点的路径数之和。而若想求得k,每个j都应该求得。

    是不是感觉很熟悉?想要求得一个点的信息,必须将所有指向它的点的信息全部求得。这让我们想起了拓扑排序。我们可以使用拓扑排序的顺序对每个点进行处理,由此可以使用非递归求得s到每个点的路径数。

    一开始,入度为0的点,也就是点s,显然其f[s]=1.

    本质还是dp的过程。

  • 相关阅读:
    浅谈SQL Server中的事务日志(五)----日志在高可用和灾难恢复中的作用
    浅谈SQL Server中的事务日志(四)----在完整恢复模式下日志的角色
    浅谈SQL Server中的事务日志(三)----在简单恢复模式下日志的角色
    Camera启动篇一
    【转】一篇不错的v4l2入门文档
    【转】open-drain与push-pull
    高通camera学习笔记五(actuator驱动参数解析)
    高通camera学习笔记四
    git精彩博文集锦
    【转】Git基础
  • 原文地址:https://www.cnblogs.com/Ning-Mew/p/7595598.html
Copyright © 2020-2023  润新知